PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.0
Adminify – White Label, Admin Menu Editor, Login Customizer v4.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
← All changes | Inc/Modules/MenuEditor/MenuEditor.php +266 -586 4.3.14.0 View file →
@@ -1,12 +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;
8 -use enshrined\svgSanitize\Sanitizer;
5 +use WPAdminify\Inc\Utils;
6 +use WPAdminify\Inc\Admin\AdminSettings;
7 +use WPAdminify\Inc\Modules\MenuEditor\MenuEditorAssets;
8 +use WPAdminify\Inc\Admin\AdminSettingsModel;
9 9 // no direct access allowed
10 10 if ( !defined( 'ABSPATH' ) ) {
11 11 exit;
12 12 }
@@ -45,73 +45,32 @@
45 45 public function __construct() {
46 46 $this->menu_settings = ( new MenuEditorOptions() )->get();
47 47 $this->options = (array) AdminSettings::get_instance()->get();
48 48 add_filter( 'upload_mimes', [$this, 'custom_icon_mime_types'] );
49 - add_filter( 'wp_handle_upload_prefilter', [$this, 'sanitize_svg_file'] );
50 - add_filter( 'admin_body_class', [$this, 'menu_editor_body_class'] );
51 - // add_filter('parent_file', [$this, 'set_menu'], 800);
52 - // 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 ) ) {
55 - add_filter( 'parent_file', [$this, 'set_menu'], 800 );
56 - add_filter( 'parent_file', [$this, 'apply_menu'], 900 );
57 - }
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'] );
49 + // add_action('admin_menu', [$this, 'jltwp_adminify_menu_editor_submenu'], 51);
50 + add_filter( 'admin_body_class', [$this, 'jltwp_adminify_menu_editor_body_class'] );
51 + add_filter( 'parent_file', [$this, 'set_menu'], 800 );
52 + add_filter( 'parent_file', [$this, 'apply_menu'], 900 );
53 + add_action( 'wp_ajax_adminify_save_menu_settings', [$this, 'adminify_save_menu_settings'] );
54 + add_action( 'wp_ajax_adminify_reset_menu_settings', [$this, 'adminify_reset_menu_settings'] );
55 + add_action( 'wp_ajax_adminify_export_menu_settings', [$this, 'adminify_export_menu_settings'] );
56 + add_action( 'wp_ajax_adminify_import_menu_settings', [$this, 'adminify_import_menu_settings'] );
57 + add_action( 'wp_ajax_adminify_file_upload', [$this, 'adminify_file_upload_callback'] );
58 + add_action( 'wp_ajax_adminify_load_custom_icons', [$this, 'adminify_load_custom_icons_callback'] );
65 59 new MenuEditorAssets();
66 60 }
67 61
68 62 public function custom_icon_mime_types( $mimes ) {
69 - if ( current_user_can( 'administrator' ) ) {
70 - $mimes['svg'] = 'image/svg+xml';
71 - }
63 + $mimes['svg'] = 'image/svg+xml';
72 64 return $mimes;
73 65 }
74 66
75 - public function sanitize_svg_file( $file ) {
76 - // Step 1: Validate File Type
77 - $file_type = wp_check_filetype( $file['name'] );
78 - // Ensure the file is an SVG
79 - if ( $file_type['ext'] === 'svg' ) {
80 - // Read the contents of the SVG file
81 - $file_contents = file_get_contents( $file['tmp_name'] );
82 - // Validate if it's an actual SVG by checking if it contains the <svg> tag
83 - if ( strpos( $file_contents, '<svg' ) === false ) {
84 - $file['error'] = 'Invalid SVG file';
85 - return $file;
86 - // Stop further processing if it's not a valid SVG
87 - }
88 - // Step 2: Sanitize the SVG File
89 - $sanitizer = new Sanitizer();
90 - $clean_svg = $sanitizer->sanitize( $file_contents );
91 - if ( $clean_svg ) {
92 - // Save the sanitized SVG back to the file
93 - file_put_contents( $file['tmp_name'], $clean_svg );
94 - } else {
95 - $file['error'] = 'Failed to sanitize the SVG file';
96 - }
97 - }
98 - return $file;
99 - }
100 -
101 67 public function filter_attachment( $value ) {
102 68 // return $value->post_title == 'adminify-custom-icon';
103 69 return strpos( $value->guid, 'adminify-custom-icon' ) !== false;
104 70 }
105 71
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 - }
72 + public function adminify_load_custom_icons_callback() {
114 73 $result['images'] = null;
115 74 $query = get_posts( [
116 75 'post_type' => 'attachment',
117 76 'numberposts' => -1,
@@ -123,28 +82,17 @@
123 82 echo wp_json_encode( $result );
124 83 die;
125 84 }
126 85
127 - public function file_upload_callback() {
86 + public function adminify_file_upload_callback() {
128 87 $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 - }
88 + check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' );
135 89 $upload_dir = wp_upload_dir();
136 90 $targeted_dir = $upload_dir['basedir'] . '/adminify-custom-icons';
137 91 if ( !is_dir( $targeted_dir ) ) {
138 92 wp_mkdir_p( $targeted_dir );
139 93 }
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.
94 + add_filter( 'upload_dir', [$this, 'adminify_icon_custom_upload_dir'] );
147 95 $files = wp_kses_post_deep( wp_unslash( $_FILES['my_file_upload'] ) );
148 96 foreach ( $files['name'] as $key => $value ) {
149 97 if ( $files['name'][$key] ) {
150 98 $file = [
@@ -169,14 +117,14 @@
169 117 $result['images'][$attachment_id] = wp_get_attachment_url( $attachment_id );
170 118 }
171 119 }
172 120 }
173 - remove_filter( 'upload_dir', [$this, 'icon_custom_upload_dir'] );
121 + remove_filter( 'upload_dir', [$this, 'adminify_icon_custom_upload_dir'] );
174 122 echo wp_json_encode( $result );
175 123 wp_die();
176 124 }
177 125
178 - public function icon_custom_upload_dir( $dir_data ) {
126 + public function adminify_icon_custom_upload_dir( $dir_data ) {
179 127 // $dir_data already you might want to use
180 128 $custom_dir = 'adminify-custom-icons';
181 129 return [
182 130 'path' => $dir_data['basedir'] . '/' . $custom_dir,
@@ -187,75 +135,10 @@
187 135 'error' => $dir_data['error'],
188 136 ];
189 137 }
190 138
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 139 // Menu Editor Body Class
257 - public function menu_editor_body_class( $classes ) {
140 + public function jltwp_adminify_menu_editor_body_class( $classes ) {
258 141 $classes .= ' adminify_menu_editor ';
259 142 return $classes;
260 143 }
261 144
@@ -270,13 +153,13 @@
270 153 foreach ( $values as $index => $in ) {
271 154 if ( is_array( $in ) ) {
272 155 $values[$index] = $this->clean_ajax_input( $in );
273 156 } else {
274 - $values[$index] = wp_strip_all_tags( $in );
157 + $values[$index] = strip_tags( $in );
275 158 }
276 159 }
277 160 } else {
278 - $values = wp_strip_all_tags( $values );
161 + $values = strip_tags( $values );
279 162 }
280 163 return $values;
281 164 }
282 165
@@ -289,25 +172,18 @@
289 172 public function ajax_error_message( $message ) {
290 173 $returndata = [];
291 174 $returndata['error'] = true;
292 175 $returndata['error_message'] = $message;
293 - return wp_json_encode( $returndata );
176 + return json_encode( $returndata );
294 177 }
295 178
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.
179 + public function adminify_save_menu_settings() {
180 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
181 + $options = wp_kses_post_deep( wp_unslash( $_POST['options'] ) );
305 182 $options = $this->clean_ajax_input( $options );
306 183 if ( $options == '' || !is_array( $options ) ) {
307 184 $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 ) );
185 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
310 186 die;
311 187 }
312 188 if ( is_array( $options ) ) {
313 189 update_option( $this->prefix, $options );
@@ -313,14 +189,13 @@
313 189 update_option( $this->prefix, $options );
314 190 $returndata = [];
315 191 $returndata['success'] = true;
316 192 $returndata['message'] = __( 'Settings saved', 'adminify' );
317 - echo wp_json_encode( $returndata );
193 + echo json_encode( $returndata );
318 194 die;
319 195 } else {
320 196 $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 ) );
197 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
323 198 die;
324 199 }
325 200 }
326 201 die;
@@ -330,15 +205,10 @@
330 205 * Menu Editor Settings Reset
331 206 *
332 207 * @return void
333 208 */
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 - }
209 + public function adminify_reset_menu_settings() {
210 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
341 211 update_option( $this->prefix, [] );
342 212 $menu_editor_options = get_option( $this->prefix );
343 213 if ( !$menu_editor_options ) {
344 214 $returndata = [];
@@ -343,14 +213,13 @@
343 213 if ( !$menu_editor_options ) {
344 214 $returndata = [];
345 215 $returndata['success'] = true;
346 216 $returndata['message'] = __( 'Settings reset', 'adminify' );
347 - echo wp_json_encode( $returndata );
217 + echo json_encode( $returndata );
348 218 die;
349 219 } else {
350 220 $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 ) );
221 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
353 222 die;
354 223 }
355 224 }
356 225 die;
@@ -360,17 +229,12 @@
360 229 * Export Menu Editor Settings
361 230 *
362 231 * @return void
363 232 */
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 - }
233 + public function adminify_export_menu_settings() {
234 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
371 235 $menu_editor_options = get_option( $this->prefix );
372 - echo wp_json_encode( $menu_editor_options );
236 + echo json_encode( $menu_editor_options );
373 237 }
374 238 die;
375 239 }
376 240
@@ -378,21 +242,14 @@
378 242 * Import Menu Editor Settings
379 243 *
380 244 * @since 1.0.0
381 245 */
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().
246 + public function adminify_import_menu_settings() {
247 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX && check_ajax_referer( 'adminify-menu-editor-security-nonce', 'security' ) > 0 ) {
248 + $new_options = wp_kses_post_deep( $_POST['settings'] );
391 249 if ( $new_options == '' || !is_array( $new_options ) ) {
392 250 $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 ) );
251 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
395 252 die;
396 253 }
397 254 if ( is_array( $new_options ) ) {
398 255 update_option( $this->prefix, $new_options );
@@ -398,14 +255,13 @@
398 255 update_option( $this->prefix, $new_options );
399 256 $returndata = [];
400 257 $returndata['success'] = true;
401 258 $returndata['message'] = __( 'Menu Imported', 'adminify' );
402 - echo wp_json_encode( $returndata );
259 + echo json_encode( $returndata );
403 260 die;
404 261 } else {
405 262 $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 ) );
263 + echo Utils::wp_kses_custom( $this->ajax_error_message( $message ) );
408 264 die;
409 265 }
410 266 }
411 267 die;
@@ -411,37 +267,8 @@
411 267 die;
412 268 }
413 269
414 270 /**
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 271 * Get menu items
445 272 *
446 273 * @param [type] $parent_file
447 274 *
@@ -460,21 +287,12 @@
460 287 public function sort_menu_settings( $thismenu ) {
461 288 $menu_settings = $this->menu_settings;
462 289 $tempmenu = [];
463 290 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 291 $next_menu_item = next( $thismenu );
473 292 $optiongroup = [];
474 293 $order = $key;
475 294 $separator = 0;
476 - $external_link = 0;
477 295 $icon = null;
478 296 $hidden_for = [];
479 297 if ( !empty( $next_menu_item ) && strpos( $next_menu_item[2], 'separator' ) !== false ) {
480 298 $separator = 1;
@@ -479,18 +297,10 @@
479 297 if ( !empty( $next_menu_item ) && strpos( $next_menu_item[2], 'separator' ) !== false ) {
480 298 $separator = 1;
481 299 }
482 300 if ( is_array( $menu_settings ) ) {
483 - // Direct slug match first, then fallback for dynamic-slug plugins (e.g. Yoast SEO)
484 301 if ( isset( $menu_settings[$current_menu_item[2]] ) ) {
485 302 $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 303 if ( isset( $optiongroup['order'] ) ) {
494 304 $order = $optiongroup['order'];
495 305 }
496 306 if ( isset( $optiongroup['separator'] ) ) {
@@ -495,11 +305,8 @@
495 305 }
496 306 if ( isset( $optiongroup['separator'] ) ) {
497 307 $separator = $optiongroup['separator'];
498 308 }
499 - if ( isset( $optiongroup['external_link'] ) ) {
500 - $external_link = $optiongroup['external_link'];
501 - }
502 309 if ( !empty( $optiongroup['icon'] ) ) {
503 310 $icon = $optiongroup['icon'];
504 311 }
505 312 if ( !empty( $optiongroup['hidden_for'] ) ) {
@@ -507,29 +314,27 @@
507 314 }
508 315 }
509 316 }
510 317 $current_menu_item['order'] = $order;
511 - $current_menu_item['hidden_for'] = $hidden_for;
512 318 $current_menu_item['separator'] = $separator;
513 - $current_menu_item['external_link'] = $external_link;
514 - // if (empty($this->options['admin_ui'])) {
515 - if ( $icon !== null ) {
516 - if ( strpos( $icon, 'dashicons ' ) !== false ) {
517 - $menu_icon = str_replace( 'dashicons ', '', $icon );
518 - $current_menu_item[6] = $menu_icon;
519 - } else {
520 - if ( strpos( $icon, ',' ) !== false ) {
521 - $menu_icon = explode( ',', $icon )[1];
319 + if ( empty( $this->options['admin_ui'] ) ) {
320 + if ( $icon !== null ) {
321 + if ( strpos( $icon, 'dashicons ' ) !== false ) {
322 + $menu_icon = str_replace( 'dashicons ', '', $icon );
323 + $current_menu_item[6] = $menu_icon;
522 324 } else {
523 - $menu_icon = 'dashicons-adminify- ' . $icon;
325 + if ( strpos( $icon, ',' ) !== false ) {
326 + $menu_icon = explode( ',', $icon )[1];
327 + } else {
328 + $menu_icon = 'dashicons-adminify- ' . $icon;
329 + }
330 + $current_menu_item[6] = $menu_icon;
524 331 }
525 - $current_menu_item[6] = $menu_icon;
526 332 }
333 + if ( $separator == 1 ) {
334 + $current_menu_item[4] = $current_menu_item[4] . ' adminify-menu-separator';
335 + }
527 336 }
528 - if ( $separator == 1 ) {
529 - $current_menu_item[4] = $current_menu_item[4] . ' adminify-menu-separator';
530 - }
531 - // }
532 337 array_push( $tempmenu, $current_menu_item );
533 338 if ( isset( $menu_settings[$current_menu_item[2]] ) ) {
534 339 unset($menu_settings[$current_menu_item[2]]);
535 340 }
@@ -535,22 +340,8 @@
535 340 }
536 341 }
537 342 if ( is_array( $menu_settings ) && !array_key_exists( 0, $menu_settings ) ) {
538 343 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 344 $new_array = [
554 345 $menu_s['name'],
555 346 'read',
556 347 ( !empty( $menu_s['link'] ) ? $menu_s['link'] : '' ),
@@ -559,33 +350,29 @@
559 350 $key,
560 351 ( !empty( $menu_s['icon'] ) ? $menu_s['icon'] : '' ),
561 352 'order' => $menu_s['order'],
562 353 'separator' => ( !empty( $menu_s['separator'] ) ? $menu_s['separator'] : 0 ),
563 - 'external_link' => ( !empty( $menu_s['external_link'] ) ? $menu_s['external_link'] : 0 ),
564 354 'hidden_for' => ( !empty( $menu_s['hidden_for'] ) ? $menu_s['hidden_for'] : [] )
565 355 ];
566 - // if (empty($this->options['admin_ui'])) {
567 - if ( strpos( $menu_s['icon'], 'dashicons ' ) !== false ) {
568 - $menu_icon = str_replace( 'dashicons ', '', $menu_s['icon'] );
569 - } else {
570 - if ( empty( $menu_s['icon'] ) || strpos( $menu_s['icon'], ',' ) !== false ) {
571 - if ( empty( $menu_s['icon'] ) ) {
572 - $menu_icon = PXLBSADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
356 + if ( empty( $this->options['admin_ui'] ) ) {
357 + if ( strpos( $menu_s['icon'], 'dashicons ' ) !== false ) {
358 + $menu_icon = str_replace( 'dashicons ', '', $menu_s['icon'] );
359 + } else {
360 + if ( empty( $menu_s['icon'] ) || strpos( $menu_s['icon'], ',' ) !== false ) {
361 + if ( empty( $menu_s['icon'] ) ) {
362 + $menu_icon = WP_ADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
363 + } else {
364 + $menu_icon = explode( ',', $menu_s['icon'] )[1];
365 + }
573 366 } else {
574 - $menu_icon = explode( ',', $menu_s['icon'] )[1];
367 + $menu_icon = 'dashicons-adminify- ' . $menu_s['icon'];
575 368 }
576 - } else {
577 - $menu_icon = 'dashicons-adminify- ' . $menu_s['icon'];
578 369 }
370 + if ( $menu_s['separator'] == 1 ) {
371 + $new_array[4] = $new_array[4] . ' adminify-menu-separator';
372 + }
373 + $new_array[6] = $menu_icon;
579 374 }
580 - if ( !empty( $menu_s['separator'] ) && $menu_s['separator'] == 1 ) {
581 - $new_array[4] = $new_array[4] . ' adminify-menu-separator';
582 - }
583 - // if (!empty($menu_s['external_link']) && $menu_s['external_link'] == 1) {
584 - // $new_array[4] = $new_array[4] . ' adminify-menu-external_link';
585 - // }
586 - $new_array[6] = $menu_icon;
587 - // }
588 375 array_push( $tempmenu, $new_array );
589 376 }
590 377 }
591 378 return $this->sort_array( $tempmenu );
@@ -697,11 +484,12 @@
697 484 $tempsub = [];
698 485 $submenu = $this->sort_sub_menu_settings( $menu, $submenu );
699 486 if ( $this->menu && is_array( $this->menu ) ) {
700 487 foreach ( $this->menu as $key => $menu_item ) {
701 - if ( empty( $menu_item[2] ) ) {
702 - continue;
703 - }
488 + // if (empty($menu_item[0])) {
489 + // continue;
490 + // }
491 + // if (strpos($menu_item[2], 'separator') !== false && !$menu_item[0]) {
704 492 if ( strpos( $menu_item[2], 'separator' ) !== false && !$menu_item[0] ) {
705 493 // Build Separator
706 494 $newitem = $this->apply_separator_settings( $menu_item, $key );
707 495 if ( $newitem ) {
@@ -711,21 +499,8 @@
711 499 // Build Top Level
712 500 $newitem = $this->apply_top_level_settings( $menu_item, $key );
713 501 if ( $newitem ) {
714 502 array_push( $tempmenu, $newitem );
715 - // Menu Editor Custom Separator
716 - if ( !empty( $newitem['separator'] ) ) {
717 - $separator_order = $this->menu[$key]['order'];
718 - $empty_separator = array(
719 - 0 => '',
720 - 1 => 'read',
721 - 2 => 'separator_' . wp_rand( 200, 1000 ) * 1000,
722 - 3 => '',
723 - 4 => 'wp-menu-separator',
724 - 'order' => $separator_order + 0.5,
725 - );
726 - array_push( $tempmenu, $empty_separator );
727 - }
728 503 $parent_key = $newitem[2];
729 504 if ( strpos( $newitem[5], 'adminify-custom-menu-' ) !== false ) {
730 505 $parent_key = $newitem[5];
731 506 }
@@ -760,9 +535,9 @@
760 535 }
761 536 $submenu_settings = $this->menu_settings[$parentname]['submenu'];
762 537 $tempsub = [];
763 538 foreach ( $subitems as $current_menu_item ) {
764 - $sub_level = apply_filters( 'pxlbsadminify/menu_editor', [
539 + $sub_level = apply_filters( 'adminify/menu_editor', [
765 540 'sub_level' => false,
766 541 ] );
767 542 if ( !empty( $sub_level['sub_level'] ) ) {
768 543 if ( empty( $current_menu_item[0] ) || $current_menu_item[2] === 'wp-adminify-settings-pricing' ) {
@@ -788,15 +563,12 @@
788 563 $current_menu_item[2] = $link;
789 564 $current_menu_item['link'] = $link;
790 565 }
791 566 }
792 - if ( isset( $optiongroup['external_link'] ) ) {
793 - $external_link = $optiongroup['external_link'];
794 - }
795 567 if ( isset( $optiongroup['hidden_for'] ) ) {
796 568 $disabled_for = $optiongroup['hidden_for'];
797 569 if ( $this->is_hidden( $disabled_for ) ) {
798 - $current_menu_item['hidden_for'] = true;
570 + $current_menu_item['hidden'] = true;
799 571 continue;
800 572 }
801 573 }
802 574 }
@@ -804,13 +576,10 @@
804 576 if ( strpos( $custom_menu, 'adminify-custom-submenu-' ) !== false ) {
805 577 if ( isset( $submenu_settings[$current_menu_item['key']]['hidden_for'] ) ) {
806 578 $disabled_for = $submenu_settings[$current_menu_item['key']]['hidden_for'];
807 579 }
808 - if ( isset( $submenu_settings[$current_menu_item['key']]['external_link'] ) ) {
809 - $external_link = $submenu_settings[$current_menu_item['key']]['external_link'];
810 - }
811 580 if ( $this->is_hidden( $disabled_for ) ) {
812 - $current_menu_item['hidden_for'] = true;
581 + $current_menu_item['hidden'] = true;
813 582 continue;
814 583 }
815 584 }
816 585 array_push( $tempsub, $current_menu_item );
@@ -834,18 +603,10 @@
834 603 $disabled_for = [];
835 604 $optiongroup = [];
836 605 $order = $key;
837 606 if ( is_array( $this->menu_settings ) ) {
838 - // Direct slug match first, then fallback for dynamic-slug plugins (e.g. Yoast SEO)
839 607 if ( isset( $this->menu_settings[$current_menu_item[2]] ) ) {
840 608 $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 609 if ( isset( $optiongroup['name'] ) ) {
849 610 $name = $optiongroup['name'];
850 611 if ( $name != '' ) {
851 612 $current_menu_item[0] = $name;
@@ -857,11 +618,8 @@
857 618 $current_menu_item[2] = $link;
858 619 $current_menu_item['link'] = $link;
859 620 }
860 621 }
861 - if ( isset( $optiongroup['external_link'] ) ) {
862 - $external_link = ( $optiongroup['external_link'] ? $optiongroup['external_link'] : '' );
863 - }
864 622 if ( isset( $optiongroup['icon'] ) ) {
865 623 $icon = $optiongroup['icon'];
866 624 if ( $icon != '' ) {
867 625 $current_menu_item['icon'] = $icon;
@@ -872,39 +630,29 @@
872 630 }
873 631 if ( isset( $optiongroup['hidden_for'] ) ) {
874 632 $disabled_for = $optiongroup['hidden_for'];
875 633 if ( $this->is_hidden( $disabled_for ) ) {
876 - $current_menu_item['hidden_for'] = true;
877 - } else {
878 - $current_menu_item['hidden_for'] = false;
634 + $current_menu_item['hidden'] = true;
879 635 }
880 636 }
881 637 }
882 638 $custom_menu = ( isset( $current_menu_item[5] ) ? $current_menu_item[5] : '' );
883 639 if ( strpos( $custom_menu, 'adminify-custom-menu-' ) !== false ) {
884 - if ( isset( $this->menu_settings[$current_menu_item[5]]['hidden_for'] ) && !empty( $this->menu_settings[$current_menu_item[5]]['hidden_for'] ) ) {
640 + if ( isset( $this->menu_settings[$current_menu_item[5]]['hidden_for'] ) ) {
885 641 $disabled_for = $this->menu_settings[$current_menu_item[5]]['hidden_for'];
886 - if ( $this->is_hidden( $disabled_for ) ) {
887 - $current_menu_item['hidden_for'] = true;
888 - }
889 642 }
890 - if ( isset( $this->menu_settings[$current_menu_item[5]]['external_link'] ) ) {
891 - $external_link = $this->menu_settings[$current_menu_item[5]]['external_link'];
643 + if ( $this->is_hidden( $disabled_for ) ) {
644 + $current_menu_item['hidden'] = true;
892 645 }
893 646 }
894 647 }
895 648 $current_menu_item['order'] = $order;
896 - // Check hidden_for: boolean true means hide, array means check via is_hidden
897 - if ( isset( $current_menu_item['hidden_for'] ) ) {
898 - if ( $current_menu_item['hidden_for'] === true ) {
649 + if ( isset( $current_menu_item['hidden'] ) ) {
650 + if ( $current_menu_item['hidden'] == true ) {
899 651 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 - }
652 + } else {
653 + return $current_menu_item;
905 654 }
906 - return $current_menu_item;
907 655 } else {
908 656 return $current_menu_item;
909 657 }
910 658 }
@@ -920,64 +668,36 @@
920 668 if ( !is_array( $disabled_for ) ) {
921 669 return false;
922 670 }
923 671 $current_user = wp_get_current_user();
672 + $current_name = $current_user->display_name;
924 673 $current_roles = $current_user->roles;
925 674 $all_roles = wp_roles()->get_names();
926 - foreach ( $current_roles as $current_role ) {
927 - if ( isset( $all_roles[$current_role] ) && in_array( $all_roles[$current_role], $disabled_for ) ) {
928 - return true;
929 - }
930 - }
931 - // Normalize disabled_for array
932 - $disabled_for_arr = [];
933 - foreach ( $disabled_for as $v ) {
934 - $disabled_for_arr[] = Utils::sluggify_with_underscores( $v );
935 - }
936 - $slugify_user_login = Utils::sluggify_with_underscores( $current_user->user_login );
937 - // Check Username
938 - if ( in_array( $current_user->user_login, $disabled_for_arr ) || in_array( $slugify_user_login, $disabled_for_arr ) ) {
675 + if ( in_array( $current_name, $disabled_for ) ) {
939 676 return true;
940 677 }
941 - // Check User Roles and Capabilities
942 - foreach ( $current_roles as $role ) {
943 - $role_obj = get_role( $role );
944 - if ( !$role_obj ) {
945 - continue;
946 - }
947 - // Check if role slug is in disabled array
948 - if ( in_array( $role, $disabled_for_arr ) ) {
678 + // MULTISITE SUPER ADMIN
679 + if ( is_super_admin() && is_multisite() ) {
680 + if ( in_array( 'Super Admin', $disabled_for ) ) {
949 681 return true;
682 + } else {
683 + return false;
950 684 }
951 - // Check if role display name is in disabled array
952 - if ( isset( $disabled_for_arr[$role] ) && (in_array( $all_roles[$role], $disabled_for ) || in_array( strtolower( $all_roles[$role] ), array_map( 'strtolower', $disabled_for ) )) ) {
953 - return true;
954 - }
955 - // Check for custom roles
956 - foreach ( $disabled_for as $disabled_item ) {
957 - // Convert role names to match WordPress format
958 - $disabled_role = str_replace( ' ', '_', strtolower( $disabled_item ) );
959 - if ( $role === $disabled_role ) {
960 - return true;
961 - }
962 - }
963 685 }
964 - // Handle Super Admin specially
965 - if ( is_super_admin( $current_user->ID ) ) {
966 - if ( in_array( 'Super Admin', $disabled_for_arr ) || in_array( 'super_admin', $disabled_for_arr ) || in_array( 'administrator', $disabled_for_arr ) ) {
686 + // NORMAL SUPER ADMIN
687 + if ( $current_user->ID === 1 ) {
688 + if ( in_array( 'Super Admin', $disabled_for ) ) {
967 689 return true;
690 + } else {
691 + return false;
968 692 }
969 - // Super admin sees everything by default unless explicitly disabled
970 - return false;
971 693 }
972 - // Special check for user ID 1 (default admin)
973 - if ( $current_user->ID === 1 ) {
974 - if ( in_array( 'Super Admin', $disabled_for_arr ) || in_array( 'super_admin', $disabled_for_arr ) || in_array( 'administrator', $disabled_for_arr ) ) {
694 + foreach ( $current_roles as $role ) {
695 + $role_name = $all_roles[$role];
696 + if ( in_array( $role_name, $disabled_for ) ) {
975 697 return true;
976 698 }
977 - return false;
978 699 }
979 - return false;
980 700 }
981 701
982 702 /**
983 703 * Applies separator menu item settings
@@ -1003,16 +723,16 @@
1003 723 }
1004 724 if ( isset( $optiongroup['hidden_for'] ) ) {
1005 725 $disabled_for = $optiongroup['hidden_for'];
1006 726 if ( $this->is_hidden( $disabled_for ) ) {
1007 - $current_menu_item['hidden_for'] = true;
727 + $current_menu_item['hidden'] = true;
1008 728 }
1009 729 }
1010 730 }
1011 731 }
1012 732 $current_menu_item['order'] = $order;
1013 - if ( isset( $current_menu_item['hidden_for'] ) ) {
1014 - if ( $current_menu_item['hidden_for'] == true ) {
733 + if ( isset( $current_menu_item['hidden'] ) ) {
734 + if ( $current_menu_item['hidden'] == true ) {
1015 735 return false;
1016 736 } else {
1017 737 return $current_menu_item;
1018 738 }
@@ -1020,8 +740,23 @@
1020 740 return $current_menu_item;
1021 741 }
1022 742 }
1023 743
744 + /**
745 + * Menu Editor Menu
746 + */
747 + public function jltwp_adminify_menu_editor_submenu() {
748 + add_submenu_page(
749 + 'wp-adminify-settings',
750 + esc_html__( 'Menu Editor by WP Adminify', 'adminify' ),
751 + esc_html__( 'Menu Editor', 'adminify' ),
752 + apply_filters( 'jltwp_adminify_capability', 'manage_options' ),
753 + 'adminify-menu-editor',
754 + // Page slug, will be displayed in URL
755 + [$this, 'jltwp_adminify_menu_editor_contents']
756 + );
757 + }
758 +
1024 759 public function get_saved_sub_menu() {
1025 760 $menu_settings = $this->menu_settings;
1026 761 $menu = $this->menu;
1027 762 $submenu = $this->submenu;
@@ -1062,8 +797,10 @@
1062 797 * Render Menu Editor
1063 798 */
1064 799 public function render_menu_editor() {
1065 800 global $wp_roles;
801 + $users = get_users();
802 + $this->users = $users;
1066 803 $this->roles = $wp_roles->roles;
1067 804 if ( $this->menu && is_array( $this->menu ) ) {
1068 805 foreach ( $this->menu as $menu_item ) {
1069 806 $next_menu_item = next( $this->menu );
@@ -1080,8 +817,25 @@
1080 817 );
1081 818 }
1082 819 }
1083 820 $this->render_add_new_menu_item();
821 + ?>
822 + <script>
823 + jQuery(function($) {
824 +
825 + $('.adminify-menu-settings').tokenize2({
826 + placeholder: '<?php
827 + esc_html_e( 'Select roles or users', 'adminify' );
828 + ?>'
829 + });
830 +
831 + $('.adminify-menu-settings').on('tokenize:select', function() {
832 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
833 + });
834 +
835 + });
836 + </script>
837 + <?php
1084 838 }
1085 839 }
1086 840
1087 841 public function get_icon( $value, $default ) {
@@ -1096,17 +850,27 @@
1096 850 */
1097 851 public function generate_user_rules_select_field( $menu_id, $disabled_for, $menu_type = 'menu' ) {
1098 852 ob_start();
1099 853 ?>
1100 - <select class="adminify-menu-settings adminify-user-role-select <?php
1101 - echo esc_attr( $menu_type );
854 + <select class="adminify-menu-settings <?php
855 + echo $menu_type;
1102 856 ?>_setting" name="hidden_for" id="<?php
1103 857 echo esc_attr( $menu_id );
1104 858 ?>-user-role-types" multiple>
1105 - <optgroup label="<?php
1106 - esc_attr_e( 'Roles', 'adminify' );
1107 - ?>">
1108 859 <?php
860 + $sel = '';
861 + // if (in_array('Super Admin', $disabled_for)) {
862 + // $sel = 'selected';
863 + // }
864 + ?>
865 +
866 + <!-- <option value="Super Admin" <?php
867 + // echo esc_attr($sel);
868 + ?>><?php
869 + // esc_html_e('Super Admin', 'adminify');
870 + ?></option> -->
871 +
872 + <?php
1109 873 foreach ( $this->roles as $role ) {
1110 874 $rolename = $role['name'];
1111 875 if ( 'administrator' == strtolower( $rolename ) ) {
1112 876 continue;
@@ -1124,40 +888,25 @@
1124 888 echo esc_html( $rolename );
1125 889 ?></option>
1126 890 <?php
1127 891 }
1128 - ?>
1129 - </optgroup>
1130 -
1131 - <optgroup label="<?php
1132 - esc_attr_e( 'Users', 'adminify' );
1133 - ?>" class="adminify-users-optgroup">
892 + foreach ( $this->users as $user ) {
893 + $username = $user->display_name;
894 + $sel = '';
895 + if ( in_array( $username, $disabled_for ) ) {
896 + $sel = 'selected';
897 + }
898 + ?>
899 + <option value="<?php
900 + echo esc_attr( $username );
901 + ?>" <?php
902 + echo esc_attr( $sel );
903 + ?>><?php
904 + echo esc_html( $username );
905 + ?></option>
1134 906 <?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 907 }
1158 908 ?>
1159 - </optgroup>
1160 909 </select>
1161 910 <?php
1162 911 return ob_get_clean();
1163 912 }
@@ -1172,16 +921,12 @@
1172 921 $current_menu_item,
1173 922 $master_sub_menu,
1174 923 $next_menu_item
1175 924 ) {
1176 - if ( empty( $current_menu_item[2] ) ) {
1177 - return;
1178 - }
1179 - // $disabled_for = '';
925 + $disabled_for = '';
1180 926 $menu_id = preg_replace( '/[^A-Za-z0-9 ]/', '', $current_menu_item[5] );
1181 927 $name = '';
1182 928 $link = '';
1183 - $external_link = '';
1184 929 $icon = '';
1185 930 $separator = '';
1186 931 $disabled_for = [];
1187 932 $optiongroup = [];
@@ -1206,11 +951,8 @@
1206 951 }
1207 952 if ( isset( $optiongroup['separator'] ) ) {
1208 953 $separator = $optiongroup['separator'];
1209 954 }
1210 - if ( isset( $optiongroup['external_link'] ) ) {
1211 - $external_link = $optiongroup['external_link'];
1212 - }
1213 955 }
1214 956 }
1215 957 $name_attr = $current_menu_item[2];
1216 958 if ( strpos( $current_menu_item[5], 'adminify-custom-menu-' ) !== false ) {
@@ -1228,11 +970,8 @@
1228 970 }
1229 971 if ( isset( $current_menu_item['separator'] ) ) {
1230 972 $separator = $current_menu_item['separator'];
1231 973 }
1232 - if ( isset( $current_menu_item['external_link'] ) ) {
1233 - $external_link = $current_menu_item['external_link'];
1234 - }
1235 974 }
1236 975 if ( !is_array( $disabled_for ) ) {
1237 976 $disabled_for = [];
1238 977 }
@@ -1327,9 +1066,9 @@
1327 1066 <label for="<?php
1328 1067 echo esc_attr( $current_menu_item[2] );
1329 1068 ?>">
1330 1069 <?php
1331 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1070 + esc_html_e( 'Hidden For Rules', 'adminify' );
1332 1071 ?>
1333 1072 </label>
1334 1073
1335 1074 <div class="select is-small">
@@ -1334,9 +1073,8 @@
1334 1073
1335 1074 <div class="select is-small">
1336 1075
1337 1076 <?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 1077 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for );
1340 1078 ?>
1341 1079
1342 1080 </div>
@@ -1341,11 +1079,10 @@
1341 1079
1342 1080 </div>
1343 1081 </div>
1344 1082 </div>
1345 -
1346 1083 <div class="columns">
1347 - <!-- <div class="column">
1084 + <div class="column">
1348 1085 <label for="">
1349 1086 <?php
1350 1087 esc_html_e( 'Change Link', 'adminify' );
1351 1088 ?>
@@ -1353,103 +1090,12 @@
1353 1090 <input class="menu_setting" name="link" type="url" placeholder="<?php
1354 1091 esc_html_e( 'New link', 'adminify' );
1355 1092 ?>" value="<?php
1356 1093 echo esc_attr( ( $name_attr != ltrim( $link, '#' ) ? $link : '' ) );
1357 - ?>" onchange="checkForLinkTarget(this)" >
1358 -
1359 - <label for="external_link-<?php
1360 - echo esc_attr( $name_attr );
1361 1094 ?>">
1362 - <?php
1363 - esc_html_e( 'New Window?', 'adminify' );
1364 - ?>
1365 - <input class="menu_setting" id="external_link-<?php
1366 - echo esc_attr( $name_attr );
1367 - ?>" name="external_link" type="checkbox" value="0" <?php
1368 - checked( (int) $external_link, 1 );
1369 - ?> disabled>
1370 -
1371 - </label>
1372 - <script>
1373 - function checkForLinkTarget(inputField) {
1374 - var checkbox = inputField.closest('.column').querySelector('input[type="checkbox"]');
1375 -
1376 - if (inputField.value.trim() !== "") {
1377 - checkbox.disabled = false; // Enable checkbox if input is not empty
1378 - } else {
1379 - checkbox.disabled = true; // Disable checkbox if input is empty
1380 - }
1381 - }
1382 - </script>
1383 - </div> -->
1384 -
1095 + </div>
1385 1096 <div class="column">
1386 1097 <label for="">
1387 - <?php
1388 - esc_html_e( 'Change Link', 'adminify' );
1389 - ?>
1390 - </label>
1391 - <input class="menu_setting" name="link" type="url"
1392 - placeholder="<?php
1393 - esc_html_e( 'New link', 'adminify' );
1394 - ?>"
1395 - value="<?php
1396 - echo esc_attr( ( $name_attr != ltrim( $link, '#' ) ? $link : '' ) );
1397 - ?>"
1398 - oninput="checkForLinkTarget(this)">
1399 - <div class="new-tab-settings" style="padding-top: 10px;">
1400 - <label for="external_link-<?php
1401 - echo esc_attr( $name_attr );
1402 - ?>" style="display: flex; align-items: center; gap: 8px;">
1403 -
1404 - <input class="menu_setting" id="external_link-<?php
1405 - echo esc_attr( $name_attr );
1406 - ?>"
1407 - name="external_link" type="checkbox" value="1"
1408 - <?php
1409 - checked( (int) $external_link, 1 );
1410 - ?> disabled style="margin-top: 0;" >
1411 - <span><?php
1412 - esc_html_e( 'New Window?', 'adminify' );
1413 - ?></span>
1414 - </label>
1415 - </div>
1416 -
1417 - <script>
1418 - // Function to validate URL
1419 - function isValidURL(url) {
1420 - // Allow absolute URLs (with http:// or https://)
1421 - var absolutePattern = /^(https?:\/\/)[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}.*$/;
1422 -
1423 - // Allow relative URLs (starting with "/")
1424 - var relativePattern = /^\/[a-zA-Z0-9-_\/]+$/;
1425 -
1426 - return absolutePattern.test(url) || relativePattern.test(url);
1427 - }
1428 -
1429 -
1430 - function checkForLinkTarget(inputField) {
1431 - var checkbox = inputField.closest('.column').querySelector('input[type="checkbox"]');
1432 -
1433 - if (isValidURL(inputField.value.trim())) {
1434 - checkbox.disabled = false; // Enable if URL is valid
1435 - } else {
1436 - checkbox.disabled = true; // Disable if invalid
1437 - checkbox.checked = false; // Also uncheck if disabled
1438 - }
1439 - }
1440 -
1441 - // Run on page load
1442 - document.addEventListener("DOMContentLoaded", function() {
1443 - document.querySelectorAll('.column input[name="link"]').forEach(function(inputField) {
1444 - checkForLinkTarget(inputField);
1445 - });
1446 - });
1447 - </script>
1448 - </div>
1449 -
1450 - <div class="column">
1451 - <label for="">
1452 1098 <?php
1453 1099 esc_html_e( 'Set Custom Icon', 'adminify' );
1454 1100 ?>
1455 1101 </label>
@@ -1462,9 +1108,9 @@
1462 1108 <?php
1463 1109 if ( !empty( $icon ) ) {
1464 1110 if ( preg_match( '/http(s?)\\:\\/\\//i', $icon ) ) {
1465 1111 $image = explode( ',', $icon );
1466 - echo '<i class=""><img width="24" height="24" src=' . esc_url( $image[1] ) . ' ></i>';
1112 + echo '<i class=""><img src=' . esc_url( $image[1] ) . ' ></i>';
1467 1113 } else {
1468 1114 ?>
1469 1115 <i class="<?php
1470 1116 echo esc_attr( $this->get_icon( esc_attr( $icon ), '' ) );
@@ -1471,11 +1117,11 @@
1471 1117 ?>"></i>
1472 1118 <?php
1473 1119 }
1474 1120 } else {
1475 - $adminify_icon = PXLBSADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
1121 + $adminify_icon = WP_ADMINIFY_ASSETS_IMAGE . 'logos/menu-icon.svg';
1476 1122 if ( empty( $icons[$default_icons] ) ) {
1477 - echo '<i class=""><img width="24" height="24" src=' . esc_url( $adminify_icon ) . ' ></i>';
1123 + echo '<i class=""><img src=' . esc_url( $adminify_icon ) . ' ></i>';
1478 1124 } else {
1479 1125 ?>
1480 1126 <i class="<?php
1481 1127 echo wp_kses_post( $this->get_icon( esc_attr( $icon ), $icons[$default_icons] ) );
@@ -1493,27 +1139,16 @@
1493 1139 </div>
1494 1140 </div>
1495 1141 </div>
1496 1142 <div class='columns'>
1497 - <?php
1498 - $upgrade_pro = '';
1499 - $separator_name_attr = '';
1500 - $upgrade_pro = 'upgrade-pro';
1501 - $separator_name_attr = Utils::upgrade_pro_notice( 'Add Separator' );
1502 - ?>
1503 -
1504 1143 <div class='column <?php
1505 - echo esc_attr( $upgrade_pro );
1144 + echo ( !jltwp_adminify()->can_use_premium_code__premium_only() ? 'upgrade-pro' : '' );
1506 1145 ?>'>
1507 - <label for="seperator-<?php
1508 - echo esc_attr( $name_attr );
1509 - ?>">
1510 - <?php
1511 - $separator_content = apply_filters( 'pxlbsadminify/menu_editor/add_separator', $separator_name_attr, $separator );
1512 - // Apply the filter
1513 - echo wp_kses_post( $separator_content || "" );
1146 + <?php
1514 1147 ?>
1515 - </label>
1148 + <?php
1149 + echo Utils::adminify_upgrade_pro( 'Add Separator' );
1150 + ?>
1516 1151 </div>
1517 1152 </div>
1518 1153 </div>
1519 1154 <?php
@@ -1614,16 +1249,36 @@
1614 1249 ?>">
1615 1250 </div>
1616 1251 <div class="column">
1617 1252 <label for=""><?php
1618 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1253 + esc_html_e( 'Hidden For Rules', 'adminify' );
1619 1254 ?></label>
1620 1255
1621 1256 <div class="select is-small">
1622 1257 <?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 1258 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for );
1625 1259 ?>
1260 +
1261 + <script>
1262 + jQuery('#<?php
1263 + echo esc_attr( $menu_id );
1264 + ?> #<?php
1265 + echo esc_attr( $menu_id );
1266 + ?>-user-role-types').tokenize2({
1267 + placeholder: '<?php
1268 + esc_html_e( 'Select roles or users', 'adminify' );
1269 + ?>'
1270 + });
1271 + jQuery(document).ready(function($) {
1272 + $('#<?php
1273 + echo esc_attr( $menu_id );
1274 + ?> #<?php
1275 + echo esc_attr( $menu_id );
1276 + ?>-user-role-types').on('tokenize:select', function(container) {
1277 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
1278 + });
1279 + })
1280 + </script>
1626 1281 </div>
1627 1282 </div>
1628 1283 </div>
1629 1284 </div>
@@ -1638,9 +1293,8 @@
1638 1293 public function build_sub_menu_item( $current_menu_item, $optiongroup, $name_attr ) {
1639 1294 $name = '';
1640 1295 $link = '';
1641 1296 $icon = '';
1642 - $external_link = '';
1643 1297 $disabled_for = [];
1644 1298 $suboptiongroup = [];
1645 1299 $menu_options = $this->menu_settings;
1646 1300 if ( isset( $optiongroup['submenu'] ) ) {
@@ -1651,11 +1305,8 @@
1651 1305 }
1652 1306 if ( isset( $suboptiongroup['link'] ) ) {
1653 1307 $link = $suboptiongroup['link'];
1654 1308 }
1655 - if ( isset( $suboptiongroup['external_link'] ) ) {
1656 - $external_link = $suboptiongroup['external_link'];
1657 - }
1658 1309 if ( isset( $suboptiongroup['icon'] ) ) {
1659 1310 $icon = $suboptiongroup['icon'];
1660 1311 }
1661 1312 if ( isset( $suboptiongroup['hidden_for'] ) ) {
@@ -1675,11 +1326,8 @@
1675 1326 }
1676 1327 if ( isset( $optiongroup['submenu'][$sub_menu_name_attr]['icon'] ) ) {
1677 1328 $icon = $optiongroup['submenu'][$sub_menu_name_attr]['icon'];
1678 1329 }
1679 - if ( isset( $optiongroup['submenu'][$sub_menu_name_attr]['external_link'] ) ) {
1680 - $external_link = $optiongroup['submenu'][$sub_menu_name_attr]['external_link'];
1681 - }
1682 1330 }
1683 1331 if ( !is_array( $disabled_for ) ) {
1684 1332 $disabled_for = [];
1685 1333 }
@@ -1728,16 +1376,38 @@
1728 1376 ?>">
1729 1377 </div>
1730 1378 <div class="column">
1731 1379 <label for=""><?php
1732 - esc_html_e( 'Hidden For Roles or Users', 'adminify' );
1380 + esc_html_e( 'Hidden For Rules', 'adminify' );
1733 1381 ?></label>
1734 1382
1735 1383 <div class="select is-small">
1384 +
1736 1385 <?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 1386 echo $this->generate_user_rules_select_field( $menu_id, $disabled_for, 'sub_menu' );
1739 1387 ?>
1388 +
1389 + <script>
1390 + jQuery('#wp-adminify-sub-menu-<?php
1391 + echo esc_attr( $menu_id );
1392 + ?> #<?php
1393 + echo esc_attr( $menu_id );
1394 + ?>-user-role-types').tokenize2({
1395 + placeholder: '<?php
1396 + esc_html_e( 'Select roles or users', 'adminify' );
1397 + ?>'
1398 + });
1399 + jQuery(document).ready(function($) {
1400 + $('#wp-adminify-sub-menu-<?php
1401 + echo esc_attr( $menu_id );
1402 + ?> #<?php
1403 + echo esc_attr( $menu_id );
1404 + ?>-user-role-types').on('tokenize:select', function(container) {
1405 + $(this).tokenize2().trigger('tokenize:search', [$(this).tokenize2().input.val()]);
1406 + });
1407 + })
1408 + </script>
1409 +
1740 1410 </div>
1741 1411 </div>
1742 1412 </div>
1743 1413 <div class="columns">
@@ -1746,30 +1416,41 @@
1746 1416 esc_html_e( 'Change Link', 'adminify' );
1747 1417 ?></label>
1748 1418 <input class="sub_menu_setting" name="link" type="url" placeholder="New link" value="<?php
1749 1419 echo esc_attr( ( $sub_menu_name_attr != ltrim( $link, '#' ) ? $link : '' ) );
1750 - ?>" onchange="checkForLinkTarget(this)" >
1751 -
1752 - <label for="external_link-<?php
1753 - echo esc_attr( $sub_menu_name_attr );
1754 1420 ?>">
1755 - <?php
1756 - esc_html_e( 'New Window?', 'adminify' );
1757 - ?>
1758 - <input class="sub_menu_setting" id="external_link-<?php
1759 - echo esc_attr( $sub_menu_name_attr );
1760 - ?>" name="external_link" type="checkbox" value="0" <?php
1761 - checked( (int) $external_link, 1 );
1762 - ?>disabled />
1763 -
1764 - </label>
1765 1421 </div>
1766 1422 <div class="column">
1767 - <label for="" style="margin-top:25px">
1768 - <?php
1769 - esc_html_e( 'Custom Icon is not allowed for Submenu', 'adminify' );
1423 + <label for=""><?php
1424 + esc_html_e( 'Set Custom Icon', 'adminify' );
1425 + ?> <i>(<?php
1426 + esc_html_e( 'Not available for Submenu.', 'adminify' );
1427 + ?>)</i></label>
1428 +
1429 + <div class="icon-picker-wrap wp-adminify-menu-icon-picker adminify-icon-picker-input icon-select-button is-clickable-no is-pulled-left">
1430 + <ul class="icon-picker">
1431 + <li class="icon-none" title="None"><i class="dashicons dashicons-dismiss"></i></li>
1432 + <?php
1433 + $custom_class = '';
1434 + $icon = '<i class="' . $this->get_icon( esc_attr( $icon ), 'dashicons dashicons-external' ) . '"></i>';
1435 + if ( strpos( $sub_menu_name_attr, 'adminify-custom-submenu-' ) !== false ) {
1436 + $custom_class = 'custom-icon';
1437 + $icon = '<img src="' . esc_url( WP_ADMINIFY_ASSETS_IMAGE ) . 'logos/menu-icon.svg" />';
1438 + }
1770 1439 ?>
1771 - </label>
1440 + <li class="select-icon <?php
1441 + echo esc_attr( $custom_class );
1442 + ?>" title="Icon Library">
1443 + <?php
1444 + echo wp_kses_post( $icon );
1445 + ?>
1446 + </li>
1447 + <input type="hidden" class="sub_menu_setting" name="icon" value="<?php
1448 + echo esc_attr( $icon );
1449 + ?>">
1450 + </ul>
1451 + </div>
1452 +
1772 1453 </div>
1773 1454 </div>
1774 1455 </div>
1775 1456 <?php
@@ -1792,10 +1473,10 @@
1792 1473 /**
1793 1474 * Add New Menu Item.
1794 1475 */
1795 1476 public function render_add_new_menu_item( $submenu = false ) {
1796 - $add_item = apply_filters( 'pxlbsadminify/menu_editor', [
1797 - 'upgrade_pro' => Utils::upgrade_pro_notice( ' ' ),
1477 + $add_item = apply_filters( 'adminify/menu_editor', [
1478 + 'upgrade_pro' => Utils::adminify_upgrade_pro( ' ' ),
1798 1479 'upgrade_class' => 'upgrade-pro',
1799 1480 ] );
1800 1481 ?>
1801 1482 <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 +1481,9 @@
1800 1481 ?>
1801 1482 <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 1483 echo esc_attr( ( $submenu ? 'submenu' : '' ) );
1803 1484 ?> <?php
1804 - echo esc_attr( $add_item['upgrade_class'] );
1485 + echo Utils::wp_kses_custom( $add_item['upgrade_class'] );
1805 1486 ?>">
1806 1487 <div class="inner-text">
1807 1488 <i class="dashicons dashicons-plus-alt"></i>
1808 1489 <span class="title"><?php
@@ -1809,9 +1490,9 @@
1809 1490 esc_html_e( 'Add Item', 'adminify' );
1810 1491 ?></span>
1811 1492 </div>
1812 1493 <?php
1813 - echo wp_kses( $add_item['upgrade_pro'], Utils::kses_allowed_html() );
1494 + echo Utils::wp_kses_custom( $add_item['upgrade_pro'] );
1814 1495 ?>
1815 1496 </div>
1816 1497 <?php
1817 1498 }
@@ -1826,15 +1507,14 @@
1826 1507
1827 1508 <div class="adminify-flex adminify-flex-center adminify-justify-between">
1828 1509 <div class="adminify-menu-editor-help-urls adminify-flex adminify-flex-center adminify-gap-2">
1829 1510 <?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(
1511 + echo Utils::adminfiy_help_urls(
1832 1512 __( 'Menu Editor', 'adminify' ),
1833 1513 'https://wpadminify.com/kb/wordpress-dashboard-menu-editor/',
1834 1514 'https://www.youtube.com/playlist?list=PLqpMw0NsHXV-EKj9Xm1DMGa6FGniHHly8',
1835 1515 'https://www.facebook.com/groups/jeweltheme',
1836 - esc_url( \PXLBSAdminify\Inc\Admin\AdminSettings::support_url() )
1516 + 'https://wpadminify.com/support/'
1837 1517 );
1838 1518 ?>
1839 1519 </div>
1840 1520
@@ -1890,9 +1570,9 @@
1890 1570 <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 1571 </svg>
1892 1572
1893 1573 <?php
1894 - esc_html_e( 'If you have Adminify Menu Module disabled, icons and label dividers won\'t change.', 'adminify' );
1574 + esc_html_e( 'If you have WP Adminify Menu Module disabled, icons and label dividers won\'t change.', 'adminify' );
1895 1575 ?>
1896 1576
1897 1577 </p>
1898 1578 </div>
@@ -1900,15 +1580,15 @@
1900 1580
1901 1581 <?php
1902 1582 }
1903 1583
1904 - public function menu_editor_contents() {
1584 + public function jltwp_adminify_menu_editor_contents() {
1905 1585 ?>
1906 1586
1907 1587 <div class="wrap">
1908 1588 <div class="wp-adminify--menu--editor--container">
1909 1589
1910 - <!-- <div id="adminify-data-saved-message"></div> -->
1590 + <!-- <div id="adminify-data-saved-message"></div> -->
1911 1591
1912 1592 <?php
1913 1593 //self::render_menu_editor_header();
1914 1594 ?>