PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.0.3.7
Adminify – White Label, Admin Menu Editor, Login Customizer v4.0.3.7
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 | Inc/Modules/MenuEditor/MenuEditor.php +160 -288 4.2.114.0.3.7 View file →
@@ -1,11 +1,12 @@
1 1 <?php
2 2
3 -namespace PXLBSAdminify\Inc\Modules\MenuEditor;
3 +namespace WPAdminify\Inc\Modules\MenuEditor;
4 4
5 -use PXLBSAdminify\Inc\Utils;
6 -use PXLBSAdminify\Inc\Admin\AdminSettings;
7 -use PXLBSAdminify\Inc\Modules\MenuEditor\MenuEditorAssets;
5 +use WPAdminify\Inc\Utils;
6 +use WPAdminify\Inc\Admin\AdminSettings;
7 +use WPAdminify\Inc\Modules\MenuEditor\MenuEditorAssets;
8 +use WPAdminify\Inc\Admin\AdminSettingsModel;
8 9 use enshrined\svgSanitize\Sanitizer;
9 10 // no direct access allowed
10 11 if ( !defined( 'ABSPATH' ) ) {
11 12 exit;
@@ -46,23 +47,22 @@
46 47 $this->menu_settings = ( new MenuEditorOptions() )->get();
47 48 $this->options = (array) AdminSettings::get_instance()->get();
48 49 add_filter( 'upload_mimes', [$this, 'custom_icon_mime_types'] );
49 50 add_filter( 'wp_handle_upload_prefilter', [$this, 'sanitize_svg_file'] );
50 - add_filter( 'admin_body_class', [$this, 'menu_editor_body_class'] );
51 + add_filter( 'admin_body_class', [$this, 'jltwp_adminify_menu_editor_body_class'] );
51 52 // add_filter('parent_file', [$this, 'set_menu'], 800);
52 53 // add_filter('parent_file', [$this, 'apply_menu'], 900);
53 - // add_action('modules_menu_editor_render', [$this, 'modules_menu_editor_render']);
54 - if ( apply_filters( 'pxlbsadminify_enable_menu_editor_render', true ) ) {
54 + // add_action('jltwp_adminify_modules_menu_editor_render', [$this, 'jltwp_adminify_modules_menu_editor_render']);
55 + if ( apply_filters( 'enable_jltwp_adminify_menu_editor_render', true ) ) {
55 56 add_filter( 'parent_file', [$this, 'set_menu'], 800 );
56 57 add_filter( 'parent_file', [$this, 'apply_menu'], 900 );
57 58 }
58 - add_action( 'wp_ajax_pxlbsadminify_save_menu_settings', [$this, 'save_menu_settings'] );
59 - add_action( 'wp_ajax_pxlbsadminify_reset_menu_settings', [$this, 'reset_menu_settings'] );
60 - add_action( 'wp_ajax_pxlbsadminify_export_menu_settings', [$this, 'export_menu_settings'] );
61 - add_action( 'wp_ajax_pxlbsadminify_import_menu_settings', [$this, 'import_menu_settings'] );
62 - add_action( 'wp_ajax_pxlbsadminify_file_upload', [$this, 'file_upload_callback'] );
63 - add_action( 'wp_ajax_pxlbsadminify_load_custom_icons', [$this, 'load_custom_icons_callback'] );
64 - add_action( 'wp_ajax_pxlbsadminify_search_users', [$this, 'search_users_callback'] );
59 + add_action( 'wp_ajax_adminify_save_menu_settings', [$this, 'adminify_save_menu_settings'] );
60 + add_action( 'wp_ajax_adminify_reset_menu_settings', [$this, 'adminify_reset_menu_settings'] );
61 + add_action( 'wp_ajax_adminify_export_menu_settings', [$this, 'adminify_export_menu_settings'] );
62 + add_action( 'wp_ajax_adminify_import_menu_settings', [$this, 'adminify_import_menu_settings'] );
63 + add_action( 'wp_ajax_adminify_file_upload', [$this, 'adminify_file_upload_callback'] );
64 + add_action( 'wp_ajax_adminify_load_custom_icons', [$this, 'adminify_load_custom_icons_callback'] );
65 65 new MenuEditorAssets();
66 66 }
67 67
68 68 public function custom_icon_mime_types( $mimes ) {
@@ -102,16 +102,9 @@
102 102 // return $value->post_title == 'adminify-custom-icon';
103 103 return strpos( $value->guid, 'adminify-custom-icon' ) !== false;
104 104 }
105 105
106 - public function load_custom_icons_callback() {
107 - // Security check - verify nonce and capability
108 - check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' );
109 - if ( !current_user_can( 'manage_options' ) ) {
110 - wp_send_json_error( array(
111 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
112 - ) );
113 - }
106 + public function adminify_load_custom_icons_callback() {
114 107 $result['images'] = null;
115 108 $query = get_posts( [
116 109 'post_type' => 'attachment',
117 110 'numberposts' => -1,
@@ -123,28 +116,17 @@
123 116 echo wp_json_encode( $result );
124 117 die;
125 118 }
126 119
127 - public function file_upload_callback() {
120 + public function adminify_file_upload_callback() {
128 121 $result['status'] = false;
129 - check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' );
130 - if ( !current_user_can( 'manage_options' ) ) {
131 - wp_send_json_error( array(
132 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
133 - ) );
134 - }
122 + check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' );
135 123 $upload_dir = wp_upload_dir();
136 124 $targeted_dir = $upload_dir['basedir'] . '/adminify-custom-icons';
137 125 if ( !is_dir( $targeted_dir ) ) {
138 126 wp_mkdir_p( $targeted_dir );
139 127 }
140 - add_filter( 'upload_dir', [$this, 'icon_custom_upload_dir'] );
141 - if ( !isset( $_FILES['my_file_upload'] ) ) {
142 - wp_send_json_error( array(
143 - 'message' => __( 'No file was uploaded.', 'adminify' ),
144 - ) );
145 - }
146 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- $_FILES is sanitized by the WP upload handler.
128 + add_filter( 'upload_dir', [$this, 'adminify_icon_custom_upload_dir'] );
147 129 $files = wp_kses_post_deep( wp_unslash( $_FILES['my_file_upload'] ) );
148 130 foreach ( $files['name'] as $key => $value ) {
149 131 if ( $files['name'][$key] ) {
150 132 $file = [
@@ -169,14 +151,14 @@
169 151 $result['images'][$attachment_id] = wp_get_attachment_url( $attachment_id );
170 152 }
171 153 }
172 154 }
173 - remove_filter( 'upload_dir', [$this, 'icon_custom_upload_dir'] );
155 + remove_filter( 'upload_dir', [$this, 'adminify_icon_custom_upload_dir'] );
174 156 echo wp_json_encode( $result );
175 157 wp_die();
176 158 }
177 159
178 - public function icon_custom_upload_dir( $dir_data ) {
160 + public function adminify_icon_custom_upload_dir( $dir_data ) {
179 161 // $dir_data already you might want to use
180 162 $custom_dir = 'adminify-custom-icons';
181 163 return [
182 164 'path' => $dir_data['basedir'] . '/' . $custom_dir,
@@ -187,75 +169,10 @@
187 169 'error' => $dir_data['error'],
188 170 ];
189 171 }
190 172
191 - /**
192 - * AJAX callback to search users for Select2
193 - * Uses 'fields' parameter for optimized database query performance
194 - */
195 - public function search_users_callback() {
196 - check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' );
197 - if ( !current_user_can( 'manage_options' ) ) {
198 - wp_send_json_error( array(
199 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
200 - ) );
201 - }
202 - $search = ( isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : '' );
203 - // If no search term or less than 3 chars, return first 3 users
204 - if ( strlen( $search ) < 3 ) {
205 - $args = array(
206 - 'number' => 3,
207 - 'orderby' => 'ID',
208 - 'order' => 'DESC',
209 - 'fields' => array('ID', 'user_login', 'display_name'),
210 - );
211 - $users = get_users( $args );
212 - $results = array();
213 - foreach ( $users as $user ) {
214 - $results[] = array(
215 - 'id' => $user->user_login,
216 - 'text' => $user->user_login . ' (' . $user->display_name . ')',
217 - );
218 - }
219 - // Get total user count efficiently
220 - $user_count = count_users();
221 - $total_users = $user_count['total_users'];
222 - wp_send_json( array(
223 - 'results' => $results,
224 - 'pagination' => array(
225 - 'more' => $total_users > 3,
226 - ),
227 - 'total_users' => $total_users,
228 - ) );
229 - return;
230 - }
231 - // Search users when 3+ characters typed
232 - $args = array(
233 - 'search' => '*' . $search . '*',
234 - 'search_columns' => array('user_login', 'user_email', 'display_name'),
235 - 'number' => 20,
236 - 'orderby' => 'display_name',
237 - 'order' => 'ASC',
238 - 'fields' => array('ID', 'user_login', 'display_name'),
239 - );
240 - $users = get_users( $args );
241 - $results = array();
242 - foreach ( $users as $user ) {
243 - $results[] = array(
244 - 'id' => $user->user_login,
245 - 'text' => $user->user_login . ' (' . $user->display_name . ')',
246 - );
247 - }
248 - wp_send_json( array(
249 - 'results' => $results,
250 - 'pagination' => array(
251 - 'more' => false,
252 - ),
253 - ) );
254 - }
255 -
256 173 // Menu Editor Body Class
257 - public function menu_editor_body_class( $classes ) {
174 + public function jltwp_adminify_menu_editor_body_class( $classes ) {
258 175 $classes .= ' adminify_menu_editor ';
259 176 return $classes;
260 177 }
261 178
@@ -270,13 +187,13 @@
270 187 foreach ( $values as $index => $in ) {
271 188 if ( is_array( $in ) ) {
272 189 $values[$index] = $this->clean_ajax_input( $in );
273 190 } else {
274 - $values[$index] = wp_strip_all_tags( $in );
191 + $values[$index] = strip_tags( $in );
275 192 }
276 193 }
277 194 } else {
278 - $values = wp_strip_all_tags( $values );
195 + $values = strip_tags( $values );
279 196 }
280 197 return $values;
281 198 }
282 199
@@ -289,25 +206,18 @@
289 206 public function ajax_error_message( $message ) {
290 207 $returndata = [];
291 208 $returndata['error'] = true;
292 209 $returndata['error_message'] = $message;
293 - return wp_json_encode( $returndata );
210 + return json_encode( $returndata );
294 211 }
295 212
296 - public function save_menu_settings() {
297 - if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' ) > 0 ) {
298 - if ( !current_user_can( 'manage_options' ) ) {
299 - wp_send_json_error( array(
300 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
301 - ) );
302 - }
303 - $options = ( isset( $_POST['options'] ) ? wp_kses_post_deep( wp_unslash( $_POST['options'] ) ) : '' );
304 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized via wp_kses_post_deep() and clean_ajax_input() below.
213 + public function adminify_save_menu_settings() {
214 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
215 + $options = wp_kses_post_deep( wp_unslash( $_POST['options'] ) );
305 216 $options = $this->clean_ajax_input( $options );
306 217 if ( $options == '' || !is_array( $options ) ) {
307 218 $message = __( 'No options supplied to save', 'adminify' );
308 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped.
309 - echo Utils::kses_custom( $this->ajax_error_message( $message ) );
219 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
310 220 die;
311 221 }
312 222 if ( is_array( $options ) ) {
313 223 update_option( $this->prefix, $options );
@@ -313,14 +223,13 @@
313 223 update_option( $this->prefix, $options );
314 224 $returndata = [];
315 225 $returndata['success'] = true;
316 226 $returndata['message'] = __( 'Settings saved', 'adminify' );
317 - echo wp_json_encode( $returndata );
227 + echo json_encode( $returndata );
318 228 die;
319 229 } else {
320 230 $message = __( 'Something went wrong', 'adminify' );
321 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped.
322 - echo Utils::kses_custom( $this->ajax_error_message( $message ) );
231 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
323 232 die;
324 233 }
325 234 }
326 235 die;
@@ -330,15 +239,10 @@
330 239 * Menu Editor Settings Reset
331 240 *
332 241 * @return void
333 242 */
334 - public function reset_menu_settings() {
335 - if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' ) > 0 ) {
336 - if ( !current_user_can( 'manage_options' ) ) {
337 - wp_send_json_error( array(
338 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
339 - ) );
340 - }
243 + public function adminify_reset_menu_settings() {
244 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
341 245 update_option( $this->prefix, [] );
342 246 $menu_editor_options = get_option( $this->prefix );
343 247 if ( !$menu_editor_options ) {
344 248 $returndata = [];
@@ -343,14 +247,13 @@
343 247 if ( !$menu_editor_options ) {
344 248 $returndata = [];
345 249 $returndata['success'] = true;
346 250 $returndata['message'] = __( 'Settings reset', 'adminify' );
347 - echo wp_json_encode( $returndata );
251 + echo json_encode( $returndata );
348 252 die;
349 253 } else {
350 254 $message = __( 'Something went wrong', 'adminify' );
351 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped.
352 - echo Utils::kses_custom( $this->ajax_error_message( $message ) );
255 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
353 256 die;
354 257 }
355 258 }
356 259 die;
@@ -360,17 +263,12 @@
360 263 * Export Menu Editor Settings
361 264 *
362 265 * @return void
363 266 */
364 - public function export_menu_settings() {
365 - if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' ) > 0 ) {
366 - if ( !current_user_can( 'manage_options' ) ) {
367 - wp_send_json_error( array(
368 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
369 - ) );
370 - }
267 + public function adminify_export_menu_settings() {
268 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
371 269 $menu_editor_options = get_option( $this->prefix );
372 - echo wp_json_encode( $menu_editor_options );
270 + echo json_encode( $menu_editor_options );
373 271 }
374 272 die;
375 273 }
376 274
@@ -378,21 +276,14 @@
378 276 * Import Menu Editor Settings
379 277 *
380 278 * @since 1.0.0
381 279 */
382 - public function import_menu_settings() {
383 - if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'pxlbsadminify-menu-editor-security-nonce', 'security' ) > 0 ) {
384 - if ( !current_user_can( 'manage_options' ) ) {
385 - wp_send_json_error( array(
386 - 'message' => __( 'You do not have permission to perform this action.', 'adminify' ),
387 - ) );
388 - }
389 - $new_options = ( isset( $_POST['settings'] ) ? wp_kses_post_deep( wp_unslash( $_POST['settings'] ) ) : '' );
390 - // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- sanitized via wp_kses_post_deep().
280 + public function adminify_import_menu_settings() {
281 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
282 + $new_options = wp_kses_post_deep( $_POST['settings'] );
391 283 if ( $new_options == '' || !is_array( $new_options ) ) {
392 284 $message = __( 'No options supplied to save', 'adminify' );
393 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped.
394 - echo Utils::kses_custom( $this->ajax_error_message( $message ) );
285 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
395 286 die;
396 287 }
397 288 if ( is_array( $new_options ) ) {
398 289 update_option( $this->prefix, $new_options );
@@ -398,14 +289,13 @@
398 289 update_option( $this->prefix, $new_options );
399 290 $returndata = [];
400 291 $returndata['success'] = true;
401 292 $returndata['message'] = __( 'Menu Imported', 'adminify' );
402 - echo wp_json_encode( $returndata );
293 + echo json_encode( $returndata );
403 294 die;
404 295 } else {
405 296 $message = __( 'Something went wrong', 'adminify' );
406 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- kses_custom() is a wp_kses() wrapper; output already escaped.
407 - echo Utils::kses_custom( $this->ajax_error_message( $message ) );
297 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
408 298 die;
409 299 }
410 300 }
411 301 die;
@@ -411,37 +301,8 @@
411 301 die;
412 302 }
413 303
414 304 /**
415 - * Find menu settings for a given slug.
416 - * Some plugins (e.g. Yoast SEO) register different top-level menu slugs
417 - * depending on user capabilities. The admin sees slug 'wpseo_dashboard'
418 - * but the editor sees 'wpseo_tools'. This method handles that mismatch
419 - * by falling back to checking if the slug appears as a submenu key.
420 - *
421 - * @param string $slug The menu slug to look up.
422 - * @return array|null The matching settings array, or null if not found.
423 - */
424 - public function find_menu_settings_by_slug( $slug ) {
425 - // Direct match
426 - if ( isset( $this->menu_settings[$slug] ) ) {
427 - return $this->menu_settings[$slug];
428 - }
429 - // Fallback: check if this slug is a submenu of any saved parent menu
430 - if ( is_array( $this->menu_settings ) ) {
431 - foreach ( $this->menu_settings as $parent_slug => $parent_settings ) {
432 - if ( !is_array( $parent_settings ) || !isset( $parent_settings['submenu'] ) || !is_array( $parent_settings['submenu'] ) ) {
433 - continue;
434 - }
435 - if ( isset( $parent_settings['submenu'][$slug] ) ) {
436 - return $parent_settings;
437 - }
438 - }
439 - }
440 - return null;
441 - }
442 -
443 - /**
444 305 * Get menu items
445 306 *
446 307 * @param [type] $parent_file
447 308 *
@@ -460,16 +321,8 @@
460 321 public function sort_menu_settings( $thismenu ) {
461 322 $menu_settings = $this->menu_settings;
462 323 $tempmenu = [];
463 324 foreach ( $thismenu as $key => $current_menu_item ) {
464 - if ( $current_menu_item[4] === "wp-menu-separator" ) {
465 - unset($thismenu[$key]);
466 - continue;
467 - }
468 - if ( !current_user_can( 'administrator' ) && $current_menu_item[2] === 'vc-welcome' ) {
469 - unset($thismenu[$key]);
470 - continue;
471 - }
472 325 $next_menu_item = next( $thismenu );
473 326 $optiongroup = [];
474 327 $order = $key;
475 328 $separator = 0;
@@ -479,18 +332,10 @@
479 332 if ( !empty( $next_menu_item ) && strpos( $next_menu_item[2], 'separator' ) !== false ) {
480 333 $separator = 1;
481 334 }
482 335 if ( is_array( $menu_settings ) ) {
483 - // Direct slug match first, then fallback for dynamic-slug plugins (e.g. Yoast SEO)
484 336 if ( isset( $menu_settings[$current_menu_item[2]] ) ) {
485 337 $optiongroup = $menu_settings[$current_menu_item[2]];
486 - } else {
487 - $fallback = $this->find_menu_settings_by_slug( $current_menu_item[2] );
488 - if ( $fallback !== null ) {
489 - $optiongroup = $fallback;
490 - }
491 - }
492 - if ( !empty( $optiongroup ) ) {
493 338 if ( isset( $optiongroup['order'] ) ) {
494 339 $order = $optiongroup['order'];
495 340 }
496 341 if ( isset( $optiongroup['separator'] ) ) {
@@ -535,22 +380,8 @@
535 380 }
536 381 }
537 382 if ( is_array( $menu_settings ) && !array_key_exists( 0, $menu_settings ) ) {
538 383 foreach ( $menu_settings as $key => $menu_s ) {
539 - // Skip if $menu_s is not an array
540 - if ( !is_array( $menu_s ) ) {
541 - continue;
542 - }
543 - // Ensure required keys exist with defaults
544 - $menu_s = wp_parse_args( $menu_s, [
545 - 'name' => '',
546 - 'link' => '',
547 - 'icon' => '',
548 - 'order' => 0,
549 - 'separator' => 0,
550 - 'external_link' => 0,
551 - 'hidden_for' => [],
552 - ] );
553 384 $new_array = [
554 385 $menu_s['name'],
555 386 'read',
556 387 ( !empty( $menu_s['link'] ) ? $menu_s['link'] : '' ),
@@ -568,9 +399,9 @@
568 399 $menu_icon = str_replace( 'dashicons ', '', $menu_s['icon'] );
569 400 } else {
570 401 if ( empty( $menu_s['icon'] ) || strpos( $menu_s['icon'], ',' ) !== false ) {
571 402 if ( empty( $menu_s['icon'] ) ) {
572 - $menu_icon = PXLBSADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
403 + $menu_icon = WP_ADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
573 404 } else {
574 405 $menu_icon = explode( ',', $menu_s['icon'] )[1];
575 406 }
576 407 } else {
@@ -717,9 +548,9 @@
717 548 $separator_order = $this->menu[$key]['order'];
718 549 $empty_separator = array(
719 550 0 => '',
720 551 1 => 'read',
721 - 2 => 'separator_' . wp_rand( 200, 1000 ) * 1000,
552 + 2 => 'separator_' . rand( 200, 1000 ) * 1000,
722 553 3 => '',
723 554 4 => 'wp-menu-separator',
724 555 'order' => $separator_order + 0.5,
725 556 );
@@ -760,9 +591,9 @@
760 591 }
761 592 $submenu_settings = $this->menu_settings[$parentname]['submenu'];
762 593 $tempsub = [];
763 594 foreach ( $subitems as $current_menu_item ) {
764 - $sub_level = apply_filters( 'pxlbsadminify/menu_editor', [
595 + $sub_level = apply_filters( 'adminify/menu_editor', [
765 596 'sub_level' => false,
766 597 ] );
767 598 if ( !empty( $sub_level['sub_level'] ) ) {
768 599 if ( empty( $current_menu_item[0] ) || $current_menu_item[2] === 'wp-adminify-settings-pricing' ) {
@@ -834,18 +665,10 @@
834 665 $disabled_for = [];
835 666 $optiongroup = [];
836 667 $order = $key;
837 668 if ( is_array( $this->menu_settings ) ) {
838 - // Direct slug match first, then fallback for dynamic-slug plugins (e.g. Yoast SEO)
839 669 if ( isset( $this->menu_settings[$current_menu_item[2]] ) ) {
840 670 $optiongroup = $this->menu_settings[$current_menu_item[2]];
841 - } else {
842 - $fallback = $this->find_menu_settings_by_slug( $current_menu_item[2] );
843 - if ( $fallback !== null ) {
844 - $optiongroup = $fallback;
845 - }
846 - }
847 - if ( !empty( $optiongroup ) ) {
848 671 if ( isset( $optiongroup['name'] ) ) {
849 672 $name = $optiongroup['name'];
850 673 if ( $name != '' ) {
851 674 $current_menu_item[0] = $name;
@@ -892,19 +715,14 @@
892 715 }
893 716 }
894 717 }
895 718 $current_menu_item['order'] = $order;
896 - // Check hidden_for: boolean true means hide, array means check via is_hidden
897 719 if ( isset( $current_menu_item['hidden_for'] ) ) {
898 720 if ( $current_menu_item['hidden_for'] === true ) {
899 721 return false;
900 - } elseif ( is_array( $current_menu_item['hidden_for'] ) && !empty( $current_menu_item['hidden_for'] ) ) {
901 - // Fallback: hidden_for is still an array (settings lookup may have missed it)
902 - if ( $this->is_hidden( $current_menu_item['hidden_for'] ) ) {
903 - return false;
904 - }
722 + } else {
723 + return $current_menu_item;
905 724 }
906 - return $current_menu_item;
907 725 } else {
908 726 return $current_menu_item;
909 727 }
910 728 }
@@ -930,13 +748,12 @@
930 748 }
931 749 // Normalize disabled_for array
932 750 $disabled_for_arr = [];
933 751 foreach ( $disabled_for as $v ) {
934 - $disabled_for_arr[] = Utils::sluggify_with_underscores( $v );
752 + $disabled_for_arr[] = jlt_adminify_sluggify_with_underscores( $v );
935 753 }
936 - $slugify_user_login = Utils::sluggify_with_underscores( $current_user->user_login );
937 754 // Check Username
938 - if ( in_array( $current_user->user_login, $disabled_for_arr ) || in_array( $slugify_user_login, $disabled_for_arr ) ) {
755 + if ( in_array( $current_user->user_login, $disabled_for_arr ) ) {
939 756 return true;
940 757 }
941 758 // Check User Roles and Capabilities
942 759 foreach ( $current_roles as $role ) {
@@ -1062,8 +879,10 @@
1062 879 * Render Menu Editor
1063 880 */
1064 881 public function render_menu_editor() {
1065 882 global $wp_roles;
883 + $users = get_users();
884 + $this->users = $users;
1066 885 $this->roles = $wp_roles->roles;
1067 886 if ( $this->menu && is_array( $this->menu ) ) {
1068 887 foreach ( $this->menu as $menu_item ) {
1069 888 $next_menu_item = next( $this->menu );
@@ -1080,8 +899,25 @@
1080 899 );
1081 900 }
1082 901 }
1083 902 $this->render_add_new_menu_item();
903 + ?>
904 + <script>
905 + jQuery(function($) {
906 +
907 + $('.adminify-menu-settings').tokenize2({
908 + placeholder: '<?php
909 + esc_html_e( 'Select roles or users', 'adminify' );
910 + ?>'
911 + });
912 +
913 + $('.adminify-menu-settings').on('tokenize:select', function() {
914 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
915 + });
916 +
917 + });
918 + </script>
919 + <?php
1084 920 }
1085 921 }
1086 922
1087 923 public function get_icon( $value, $default ) {
@@ -1096,17 +932,27 @@
1096 932 */
1097 933 public function generate_user_rules_select_field( $menu_id, $disabled_for, $menu_type = 'menu' ) {
1098 934 ob_start();
1099 935 ?>
1100 - <select class="adminify-menu-settings adminify-user-role-select <?php
1101 - echo esc_attr( $menu_type );
936 + <select class="adminify-menu-settings <?php
937 + echo $menu_type;
1102 938 ?>_setting" name="hidden_for" id="<?php
1103 939 echo esc_attr( $menu_id );
1104 940 ?>-user-role-types" multiple>
1105 - <optgroup label="<?php
1106 - esc_attr_e( 'Roles', 'adminify' );
1107 - ?>">
1108 941 <?php
942 + $sel = '';
943 + // if (in_array('Super Admin', $disabled_for)) {
944 + // $sel = 'selected';
945 + // }
946 + ?>
947 +
948 + <!-- <option value="Super Admin" <?php
949 + // echo esc_attr($sel);
950 + ?>><?php
951 + // esc_html_e('Super Admin', 'adminify');
952 + ?></option> -->
953 +
954 + <?php
1109 955 foreach ( $this->roles as $role ) {
1110 956 $rolename = $role['name'];
1111 957 if ( 'administrator' == strtolower( $rolename ) ) {
1112 958 continue;
@@ -1124,40 +970,26 @@
1124 970 echo esc_html( $rolename );
1125 971 ?></option>
1126 972 <?php
1127 973 }
1128 - ?>
1129 - </optgroup>
1130 -
1131 - <optgroup label="<?php
1132 - esc_attr_e( 'Users', 'adminify' );
1133 - ?>" class="adminify-users-optgroup">
974 + foreach ( $this->users as $user ) {
975 + $username = $user->display_name;
976 + $user_login = $user->user_login;
977 + $sel = '';
978 + if ( in_array( $username, $disabled_for ) ) {
979 + $sel = 'selected';
980 + }
981 + ?>
982 + <option value="<?php
983 + echo wp_kses_post( $user_login );
984 + ?>" <?php
985 + echo esc_attr( $sel );
986 + ?>><?php
987 + echo wp_kses_post( $user_login );
988 + ?></option>
1134 989 <?php
1135 - // Only include pre-selected users in HTML (AJAX will populate dropdown)
1136 - foreach ( $disabled_for as $item ) {
1137 - // Check if this is a user (not a role)
1138 - $is_role = false;
1139 - foreach ( $this->roles as $role ) {
1140 - if ( $role['name'] === $item ) {
1141 - $is_role = true;
1142 - break;
1143 - }
1144 - }
1145 - if ( !$is_role ) {
1146 - $user = get_user_by( 'login', $item );
1147 - if ( $user ) {
1148 - ?>
1149 - <option value="<?php
1150 - echo esc_attr( $user->user_login );
1151 - ?>" selected><?php
1152 - echo esc_html( $user->user_login . ' (' . $user->display_name . ')' );
1153 - ?></option>
1154 - <?php
1155 - }
1156 - }
1157 990 }
1158 991 ?>
1159 - </optgroup>
1160 992 </select>
1161 993 <?php
1162 994 return ob_get_clean();
1163 995 }
@@ -1327,9 +1159,9 @@
1327 1159 <label for="<?php
1328 1160 echo esc_attr( $current_menu_item[2] );
1329 1161 ?>">
1330 1162 <?php
1331 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1163 + esc_html_e( 'Hidden For Rules', 'adminify' );
1332 1164 ?>
1333 1165 </label>
1334 1166
1335 1167 <div class="select is-small">
@@ -1334,9 +1166,8 @@
1334 1166
1335 1167 <div class="select is-small">
1336 1168
1337 1169 <?php
1338 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- generate_user_rules_select_field() returns a trusted <select> template with form inputs that wp_kses_post() would strip; values inside are escaped.
1339 1170 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for );
1340 1171 ?>
1341 1172
1342 1173 </div>
@@ -1462,9 +1293,9 @@
1462 1293 <?php
1463 1294 if ( !empty( $icon ) ) {
1464 1295 if ( preg_match( '/http(s?)\\:\\/\\//i', $icon ) ) {
1465 1296 $image = explode( ',', $icon );
1466 - echo '<i class=""><img width="24" height="24" src=' . esc_url( $image[1] ) . ' ></i>';
1297 + echo '<i class=""><img src=' . esc_url( $image[1] ) . ' ></i>';
1467 1298 } else {
1468 1299 ?>
1469 1300 <i class="<?php
1470 1301 echo esc_attr( $this->get_icon( esc_attr( $icon ), '' ) );
@@ -1471,11 +1302,11 @@
1471 1302 ?>"></i>
1472 1303 <?php
1473 1304 }
1474 1305 } else {
1475 - $adminify_icon = PXLBSADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
1306 + $adminify_icon = WP_ADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
1476 1307 if ( empty( $icons[$default_icons] ) ) {
1477 - echo '<i class=""><img width="24" height="24" src=' . esc_url( $adminify_icon ) . ' ></i>';
1308 + echo '<i class=""><img src=' . esc_url( $adminify_icon ) . ' ></i>';
1478 1309 } else {
1479 1310 ?>
1480 1311 <i class="<?php
1481 1312 echo wp_kses_post( $this->get_icon( esc_attr( $icon ), $icons[$default_icons] ) );
@@ -1497,9 +1328,9 @@
1497 1328 <?php
1498 1329 $upgrade_pro = '';
1499 1330 $separator_name_attr = '';
1500 1331 $upgrade_pro = 'upgrade-pro';
1501 - $separator_name_attr = Utils::upgrade_pro_notice( 'Add Separator' );
1332 + $separator_name_attr = Utils::adminify_upgrade_pro( 'Add Separator' );
1502 1333 ?>
1503 1334
1504 1335 <div class='column <?php
1505 1336 echo esc_attr( $upgrade_pro );
@@ -1507,11 +1338,11 @@
1507 1338 <label for="seperator-<?php
1508 1339 echo esc_attr( $name_attr );
1509 1340 ?>">
1510 1341 <?php
1511 - $separator_content = apply_filters( 'pxlbsadminify/menu_editor/add_separator', $separator_name_attr, $separator );
1342 + $separator_content = apply_filters( 'adminify/menu_editor/add_separator', $separator_name_attr, $separator );
1512 1343 // Apply the filter
1513 - echo wp_kses_post( $separator_content || "" );
1344 + echo $separator_content;
1514 1345 ?>
1515 1346 </label>
1516 1347 </div>
1517 1348 </div>
@@ -1614,16 +1445,36 @@
1614 1445 ?>">
1615 1446 </div>
1616 1447 <div class="column">
1617 1448 <label for=""><?php
1618 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1449 + esc_html_e( 'Hidden For Rules', 'adminify' );
1619 1450 ?></label>
1620 1451
1621 1452 <div class="select is-small">
1622 1453 <?php
1623 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- generate_user_rules_select_field() returns a trusted <select> template with form inputs that wp_kses_post() would strip; values inside are escaped.
1624 1454 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for );
1625 1455 ?>
1456 +
1457 + <script>
1458 + jQuery('#<?php
1459 + echo esc_attr( $menu_id );
1460 + ?> #<?php
1461 + echo esc_attr( $menu_id );
1462 + ?>-user-role-types').tokenize2({
1463 + placeholder: '<?php
1464 + esc_html_e( 'Select roles or users', 'adminify' );
1465 + ?>'
1466 + });
1467 + jQuery(document).ready(function($) {
1468 + $('#<?php
1469 + echo esc_attr( $menu_id );
1470 + ?> #<?php
1471 + echo esc_attr( $menu_id );
1472 + ?>-user-role-types').on('tokenize:select', function(container) {
1473 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
1474 + });
1475 + })
1476 + </script>
1626 1477 </div>
1627 1478 </div>
1628 1479 </div>
1629 1480 </div>
@@ -1728,16 +1579,38 @@
1728 1579 ?>">
1729 1580 </div>
1730 1581 <div class="column">
1731 1582 <label for=""><?php
1732 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1583 + esc_html_e( 'Hidden For Rules', 'adminify' );
1733 1584 ?></label>
1734 1585
1735 1586 <div class="select is-small">
1587 +
1736 1588 <?php
1737 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- generate_user_rules_select_field() returns a trusted <select> template with form inputs that wp_kses_post() would strip; values inside are escaped.
1738 1589 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for, 'sub_menu' );
1739 1590 ?>
1591 +
1592 + <script>
1593 + jQuery('#wp-adminify-sub-menu-<?php
1594 + echo esc_attr( $menu_id );
1595 + ?> #<?php
1596 + echo esc_attr( $menu_id );
1597 + ?>-user-role-types').tokenize2({
1598 + placeholder: '<?php
1599 + esc_html_e( 'Select roles or users', 'adminify' );
1600 + ?>'
1601 + });
1602 + jQuery(document).ready(function($) {
1603 + $('#wp-adminify-sub-menu-<?php
1604 + echo esc_attr( $menu_id );
1605 + ?> #<?php
1606 + echo esc_attr( $menu_id );
1607 + ?>-user-role-types').on('tokenize:select', function(container) {
1608 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
1609 + });
1610 + })
1611 + </script>
1612 +
1740 1613 </div>
1741 1614 </div>
1742 1615 </div>
1743 1616 <div class="columns">
@@ -1792,10 +1665,10 @@
1792 1665 /**
1793 1666 * Add New Menu Item.
1794 1667 */
1795 1668 public function render_add_new_menu_item( $submenu = false ) {
1796 - $add_item = apply_filters( 'pxlbsadminify/menu_editor', [
1797 - 'upgrade_pro' => Utils::upgrade_pro_notice( ' ' ),
1669 + $add_item = apply_filters( 'adminify/menu_editor', [
1670 + 'upgrade_pro' => Utils::adminify_upgrade_pro( ' ' ),
1798 1671 'upgrade_class' => 'upgrade-pro',
1799 1672 ] );
1800 1673 ?>
1801 1674 <div class="adminify-accordion adminify-add-new-menu-editor-item upgrade-pro adminify-field adminify-field-switcher adminify-depend-visible adminify-depend-on adminify-pro-notice <?php
@@ -1800,9 +1673,9 @@
1800 1673 ?>
1801 1674 <div class="adminify-accordion adminify-add-new-menu-editor-item upgrade-pro adminify-field adminify-field-switcher adminify-depend-visible adminify-depend-on adminify-pro-notice <?php
1802 1675 echo esc_attr( ( $submenu ? 'submenu' : '' ) );
1803 1676 ?> <?php
1804 - echo esc_attr( $add_item['upgrade_class'] );
1677 + echo Utils::wp_kses_custom( $add_item['upgrade_class'] );
1805 1678 ?>">
1806 1679 <div class="inner-text">
1807 1680 <i class="dashicons dashicons-plus-alt"></i>
1808 1681 <span class="title"><?php
@@ -1809,9 +1682,9 @@
1809 1682 esc_html_e( 'Add Item', 'adminify' );
1810 1683 ?></span>
1811 1684 </div>
1812 1685 <?php
1813 - echo wp_kses( $add_item['upgrade_pro'], Utils::kses_allowed_html() );
1686 + echo Utils::wp_kses_custom( $add_item['upgrade_pro'] );
1814 1687 ?>
1815 1688 </div>
1816 1689 <?php
1817 1690 }
@@ -1826,15 +1699,14 @@
1826 1699
1827 1700 <div class="adminify-flex adminify-flex-center adminify-justify-between">
1828 1701 <div class="adminify-menu-editor-help-urls adminify-flex adminify-flex-center adminify-gap-2">
1829 1702 <?php
1830 - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- help_urls() returns a trusted template containing inline SVG icons that wp_kses_post() would strip; URLs inside are passed through esc_url().
1831 - echo Utils::help_urls(
1703 + echo Utils::adminfiy_help_urls(
1832 1704 __( 'Menu Editor', 'adminify' ),
1833 1705 'https://wpadminify.com/kb/wordpress-dashboard-menu-editor/',
1834 1706 'https://www.youtube.com/playlist?list=PLqpMw0NsHXV-EKj9Xm1DMGa6FGniHHly8',
1835 1707 'https://www.facebook.com/groups/jeweltheme',
1836 - esc_url( \PXLBSAdminify\Inc\Admin\AdminSettings::support_url() )
1708 + \WPAdminify\Inc\Admin\AdminSettings::support_url()
1837 1709 );
1838 1710 ?>
1839 1711 </div>
1840 1712
@@ -1890,9 +1762,9 @@
1890 1762 <path fill-rule="evenodd" clip-rule="evenodd" d="M8.00065 1.33334C4.31865 1.33334 1.33398 4.31801 1.33398 8.00001C1.33398 11.682 4.31865 14.6667 8.00065 14.6667C11.6827 14.6667 14.6673 11.682 14.6673 8.00001C14.6673 4.31801 11.6827 1.33334 8.00065 1.33334ZM2.66732 8.00001C2.66732 9.4145 3.22922 10.7711 4.22942 11.7712C5.22961 12.7714 6.58616 13.3333 8.00065 13.3333C9.41514 13.3333 10.7717 12.7714 11.7719 11.7712C12.7721 10.7711 13.334 9.4145 13.334 8.00001C13.334 6.58552 12.7721 5.22897 11.7719 4.22877C10.7717 3.22858 9.41514 2.66668 8.00065 2.66668C6.58616 2.66668 5.22961 3.22858 4.22942 4.22877C3.22922 5.22897 2.66732 6.58552 2.66732 8.00001V8.00001Z" fill="#4E4B66" />
1891 1763 </svg>
1892 1764
1893 1765 <?php
1894 - esc_html_e( 'If you have Adminify Menu Module disabled, icons and label dividers won\'t change.', 'adminify' );
1766 + esc_html_e( 'If you have WP Adminify Menu Module disabled, icons and label dividers won\'t change.', 'adminify' );
1895 1767 ?>
1896 1768
1897 1769 </p>
1898 1770 </div>
@@ -1900,9 +1772,9 @@
1900 1772
1901 1773 <?php
1902 1774 }
1903 1775
1904 - public function menu_editor_contents() {
1776 + public function jltwp_adminify_menu_editor_contents() {
1905 1777 ?>
1906 1778
1907 1779 <div class="wrap">
1908 1780 <div class="wp-adminify--menu--editor--container">