Nav Menu Roles - Version 1.9.3

Version Description

  • Check all object properties exist before accessing. Resolves PHP notices for custom menu items.
Download this release

Release Info

Developer helgatheviking
Plugin Icon 128x128 Nav Menu Roles
Version 1.9.3
Comparing to
See all releases

Code changes from version 1.9.2 to 1.9.3

Files changed (2) hide show
  1. nav-menu-roles.php +68 -51
  2. readme.txt +35 -2
nav-menu-roles.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Nav Menu Roles
4
  Plugin URI: http://www.kathyisawesome.com/449/nav-menu-roles/
5
  Description: Hide custom menu items based on user roles.
6
- Version: 1.9.2
7
  Author: Kathy Darling
8
  Author URI: http://www.kathyisawesome.com
9
  License: GPL-3.0
@@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA02110-1301USA
26
  */
27
 
28
 
29
- // don't load directly
30
  if ( ! function_exists( 'is_admin' ) ) {
31
  header( 'Status: 403 Forbidden' );
32
  header( 'HTTP/1.1 403 Forbidden' );
@@ -48,13 +48,13 @@ class Nav_Menu_Roles {
48
  * @constant string donate url
49
  * @since 1.9.1
50
  */
51
- CONST DONATE_URL = "https://www.youcaring.com/wnt-residency";
52
 
53
  /**
54
  * @constant string version number
55
  * @since 1.7.0
56
  */
57
- CONST VERSION = '1.9.2';
58
 
59
  /**
60
  * Main Nav Menu Roles Instance
@@ -79,7 +79,7 @@ class Nav_Menu_Roles {
79
  * @since 1.5
80
  */
81
  public function __clone() {
82
- _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' , 'nav-menu-roles'), '1.5' );
83
  }
84
 
85
  /**
@@ -88,7 +88,7 @@ class Nav_Menu_Roles {
88
  * @since 1.5
89
  */
90
  public function __wakeup() {
91
- _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?' , 'nav-menu-roles'), '1.5' );
92
  }
93
 
94
  /**
@@ -99,37 +99,37 @@ class Nav_Menu_Roles {
99
  */
100
  public function __construct(){
101
 
102
- // Admin functions
103
  add_action( 'admin_init', array( $this, 'admin_init' ) );
104
 
105
- // load the textdomain
106
  add_action( 'init', array( $this, 'load_text_domain' ) );
107
 
108
- // add FAQ and Donate link to plugin
109
  add_filter( 'plugin_row_meta', array( $this, 'add_action_links' ), 10, 2 );
110
 
111
- // switch the admin walker
112
  add_filter( 'wp_edit_nav_menu_walker', array( $this, 'edit_nav_menu_walker' ) );
113
 
114
- // add new fields via hook
115
  add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'custom_fields' ), 10, 4 );
116
 
117
- // add some JS
118
  add_action( 'admin_enqueue_scripts' , array( $this, 'enqueue_scripts' ) );
119
 
120
- // save the menu item meta
121
  add_action( 'wp_update_nav_menu_item', array( $this, 'nav_update'), 10, 2 );
122
 
123
- // add meta to menu item
124
  add_filter( 'wp_setup_nav_menu_item', array( $this, 'setup_nav_item' ) );
125
 
126
- // exclude items via filter instead of via custom Walker
127
  if ( ! is_admin() ) {
128
- $priority = 20; // Because WP_Customize_Nav_Menu_Item_Setting::filter_wp_get_nav_menu_items() runs at 10.
129
- add_filter( 'wp_get_nav_menu_items', array( $this, 'exclude_menu_items' ), $priority );
130
  }
131
 
132
- // upgrade routine
133
  add_action( 'plugins_loaded', array( $this, 'maybe_upgrade' ) );
134
 
135
  }
@@ -142,7 +142,7 @@ class Nav_Menu_Roles {
142
  */
143
  public function admin_init() {
144
 
145
- // Register Importer
146
  $this->register_importer();
147
 
148
  }
@@ -156,14 +156,14 @@ class Nav_Menu_Roles {
156
  * @return void
157
  */
158
  public function register_importer(){
159
- // Register the new importer
160
  if ( defined( 'WP_LOAD_IMPORTERS' ) ) {
161
 
162
  include_once( plugin_dir_path( __FILE__ ) . 'inc/class.Nav_Menu_Roles_Import.php');
163
  // Register the custom importer we've created.
164
  $roles_import = new Nav_Menu_Roles_Import();
165
 
166
- register_importer('nav_menu_roles', __('Nav Menu Roles', 'nav-menu-roles'), sprintf( __('Import %snav menu roles%s and other menu item meta skipped by the default importer', 'nav-menu-roles'), '<strong>', '</strong>'), array( $roles_import, 'dispatch' ) );
167
 
168
  }
169
 
@@ -171,10 +171,9 @@ class Nav_Menu_Roles {
171
 
172
  /**
173
  * Make Plugin Translation-ready
174
- * CALLBACK FUNCTION FOR: add_action( 'plugins_loaded', array( $this,'load_text_domain'));
175
  * @since 1.0
176
  */
177
-
178
  public function load_text_domain() {
179
  load_plugin_textdomain( 'nav-menu-roles', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
180
  }
@@ -182,6 +181,7 @@ class Nav_Menu_Roles {
182
 
183
  /**
184
  * Display a Notice if plugin conflicts with another
 
185
  * @since 1.5
186
  * @deprecated will removed in 2.0
187
  */
@@ -192,6 +192,7 @@ class Nav_Menu_Roles {
192
 
193
  /**
194
  * Allow the notice to be dismissable
 
195
  * @since 1.6
196
  * @deprecated will removed in 2.0
197
  */
@@ -201,6 +202,7 @@ class Nav_Menu_Roles {
201
 
202
  /**
203
  * Delete the transient when a plugin is activated or deactivated
 
204
  * @since 1.5
205
  * @deprecated will removed in 2.0
206
  */
@@ -212,9 +214,10 @@ class Nav_Menu_Roles {
212
 
213
  /**
214
  * Add docu link
 
 
215
  * @param array $plugin_meta
216
  * @param string $plugin_file
217
- * @since 1.7.3
218
  */
219
  public function add_action_links( $plugin_meta, $plugin_file ) {
220
  if( $plugin_file == plugin_basename(__FILE__) ){
@@ -227,17 +230,18 @@ class Nav_Menu_Roles {
227
 
228
  /**
229
  * Override the Admin Menu Walker
 
230
  * @since 1.0
231
  */
232
  public function edit_nav_menu_walker( $walker ) {
233
  if( ! class_exists( 'Walker_Nav_Menu_Edit_Roles' ) ){
234
  global $wp_version;
235
  if ( version_compare( $wp_version, '4.7', '>=' ) ){
236
- require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles_4.7.php');
237
  } else if ( version_compare( $wp_version, '4.5', '>=' ) ){
238
- require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles_4.5.php');
239
  } else {
240
- require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles.php');
241
  }
242
  }
243
  return 'Walker_Nav_Menu_Edit_Roles';
@@ -262,7 +266,6 @@ class Nav_Menu_Roles {
262
  */
263
  $display_roles = apply_filters( 'nav_menu_roles', $wp_roles->role_names, $item );
264
 
265
-
266
  /**
267
  * If no roles are being used, don't display the role selection radio buttons at all.
268
  * Unless something deliberately removes the WordPress roles from this list, nothing will
@@ -277,20 +280,20 @@ class Nav_Menu_Roles {
277
  /* Get the roles saved for the post. */
278
  $roles = get_post_meta( $item->ID, '_nav_menu_role', true );
279
 
280
- // by default nothing is checked (will match "everyone" radio)
281
  $logged_in_out = '';
282
 
283
- // specific roles are saved as an array, so "in" or an array equals "in" is checked
284
  if( is_array( $roles ) || $roles == 'in' ){
285
  $logged_in_out = 'in';
286
  } else if ( $roles == 'out' ){
287
  $logged_in_out = 'out';
288
  }
289
 
290
- // the specific roles to check
291
  $checked_roles = is_array( $roles ) ? $roles : false;
292
 
293
- // whether to display the role checkboxes
294
  $hidden = $logged_in_out == 'in' ? '' : 'display: none;';
295
 
296
  ?>
@@ -360,9 +363,9 @@ class Nav_Menu_Roles {
360
 
361
  /**
362
  * Save the roles as menu item meta
363
- * @return null
364
  * @since 1.4
365
- *
366
  */
367
  public function enqueue_scripts( $hook ){
368
  if ( $hook == 'nav-menus.php' ){
@@ -373,15 +376,16 @@ class Nav_Menu_Roles {
373
 
374
  /**
375
  * Save the roles as menu item meta
376
- * @return string
377
  * @since 1.0
 
378
  */
379
  public function nav_update( $menu_id, $menu_item_db_id ) {
380
  global $wp_roles;
381
 
382
  $allowed_roles = apply_filters( 'nav_menu_roles', $wp_roles->role_names );
383
 
384
- // verify this came from our screen and with proper authorization.
385
  if ( ! isset( $_POST['nav-menu-role-nonce'] ) || ! wp_verify_nonce( $_POST['nav-menu-role-nonce'], 'nav-menu-nonce-name' ) ){
386
  return;
387
  }
@@ -392,7 +396,7 @@ class Nav_Menu_Roles {
392
 
393
  $custom_roles = array();
394
 
395
- // only save allowed roles
396
  foreach( (array) $_POST['nav-menu-role'][$menu_item_db_id] as $role ) {
397
  if ( array_key_exists ( $role, $allowed_roles ) ) {
398
  $custom_roles[] = $role;
@@ -415,14 +419,18 @@ class Nav_Menu_Roles {
415
  /**
416
  * Adds value of new field to $item object
417
  * is be passed to Walker_Nav_Menu_Edit_Custom
 
418
  * @since 1.0
419
  */
420
  public function setup_nav_item( $menu_item ) {
421
 
422
- $roles = get_post_meta( $menu_item->ID, '_nav_menu_role', true );
 
 
423
 
424
- if ( ! empty( $roles ) ) {
425
- $menu_item->roles = $roles;
 
426
  }
427
  return $menu_item;
428
  }
@@ -434,6 +442,8 @@ class Nav_Menu_Roles {
434
  *
435
  * @since 1.2
436
  *
 
 
437
  * Multisite compatibility added in 1.9.0
438
  * by @open-dsi https://www.open-dsi.fr/ with props to @fiech
439
  */
@@ -443,21 +453,20 @@ class Nav_Menu_Roles {
443
 
444
  if( ! empty( $items ) ) {
445
 
446
- // Iterate over the items to search and destroy
447
  foreach ( $items as $key => $item ) {
448
 
449
  $visible = true;
450
 
451
- // hide any item that is the child of a hidden item
452
- if( in_array( $item->menu_item_parent, $hide_children_of ) ){
453
  $visible = false;
454
- $hide_children_of[] = $item->ID; // for nested menus
455
  }
456
 
457
- // check any item that has NMR roles set
458
  if( $visible && isset( $item->roles ) ) {
459
 
460
- // check all logged in, all logged out, or role
461
  switch( $item->roles ) {
462
  case 'in' :
463
  /**
@@ -496,12 +505,20 @@ class Nav_Menu_Roles {
496
 
497
  }
498
 
499
- // add filter to work with plugins that don't use traditional roles
 
 
 
 
 
 
500
  $visible = apply_filters( 'nav_menu_roles_item_visibility', $visible, $item );
501
 
502
- // unset non-visible item
503
  if ( ! $visible ) {
504
- $hide_children_of[] = $item->ID; // store ID of item
 
 
505
  unset( $items[$key] ) ;
506
  }
507
 
@@ -522,7 +539,7 @@ class Nav_Menu_Roles {
522
  public function maybe_upgrade() {
523
  $db_version = get_option( 'nav_menu_roles_db_version', false );
524
 
525
- // 1.7.7 upgrade: changed the debug notice so the old transient is invalid
526
  if ( $db_version === false || version_compare( '1.7.7', $db_version, '<' ) ) {
527
  update_option( 'nav_menu_roles_db_version', self::VERSION );
528
  }
@@ -534,7 +551,7 @@ endif; // class_exists check
534
 
535
 
536
  /**
537
- * Launch the whole plugin
538
  * Returns the main instance of Nav Menu Roles to prevent the need to use globals.
539
  *
540
  * @since 1.5
3
  Plugin Name: Nav Menu Roles
4
  Plugin URI: http://www.kathyisawesome.com/449/nav-menu-roles/
5
  Description: Hide custom menu items based on user roles.
6
+ Version: 1.9.3
7
  Author: Kathy Darling
8
  Author URI: http://www.kathyisawesome.com
9
  License: GPL-3.0
26
  */
27
 
28
 
29
+ // Don't load directly.
30
  if ( ! function_exists( 'is_admin' ) ) {
31
  header( 'Status: 403 Forbidden' );
32
  header( 'HTTP/1.1 403 Forbidden' );
48
  * @constant string donate url
49
  * @since 1.9.1
50
  */
51
+ CONST DONATE_URL = "https://www.paypal.com/fundraiser/110230052184687338/charity/1451316";
52
 
53
  /**
54
  * @constant string version number
55
  * @since 1.7.0
56
  */
57
+ CONST VERSION = '1.9.3';
58
 
59
  /**
60
  * Main Nav Menu Roles Instance
79
  * @since 1.5
80
  */
81
  public function __clone() {
82
+ _doing_it_wrong( __FUNCTION__, __( 'Cloning this object is forbidden.' , 'nav-menu-roles' ), '1.5' );
83
  }
84
 
85
  /**
88
  * @since 1.5
89
  */
90
  public function __wakeup() {
91
+ _doing_it_wrong( __FUNCTION__, __( 'Unserializing instances of this class is forbidden.' , 'nav-menu-roles' ), '1.5' );
92
  }
93
 
94
  /**
99
  */
100
  public function __construct(){
101
 
102
+ // Admin functions.
103
  add_action( 'admin_init', array( $this, 'admin_init' ) );
104
 
105
+ // Load the textdomain.
106
  add_action( 'init', array( $this, 'load_text_domain' ) );
107
 
108
+ // Add FAQ and Donate link to plugin.
109
  add_filter( 'plugin_row_meta', array( $this, 'add_action_links' ), 10, 2 );
110
 
111
+ // Switch the admin walker.
112
  add_filter( 'wp_edit_nav_menu_walker', array( $this, 'edit_nav_menu_walker' ) );
113
 
114
+ // Add new fields via hook.
115
  add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'custom_fields' ), 10, 4 );
116
 
117
+ // Add some JS.
118
  add_action( 'admin_enqueue_scripts' , array( $this, 'enqueue_scripts' ) );
119
 
120
+ // Save the menu item meta.
121
  add_action( 'wp_update_nav_menu_item', array( $this, 'nav_update'), 10, 2 );
122
 
123
+ // Add meta to menu item.
124
  add_filter( 'wp_setup_nav_menu_item', array( $this, 'setup_nav_item' ) );
125
 
126
+ // Exclude items via filter instead of via custom Walker.
127
  if ( ! is_admin() ) {
128
+ // Because WP_Customize_Nav_Menu_Item_Setting::filter_wp_get_nav_menu_items() runs at 10.
129
+ add_filter( 'wp_get_nav_menu_items', array( $this, 'exclude_menu_items' ), 20 );
130
  }
131
 
132
+ // Upgrade routine.
133
  add_action( 'plugins_loaded', array( $this, 'maybe_upgrade' ) );
134
 
135
  }
142
  */
143
  public function admin_init() {
144
 
145
+ // Register Importer.
146
  $this->register_importer();
147
 
148
  }
156
  * @return void
157
  */
158
  public function register_importer(){
159
+ // Register the new importer.
160
  if ( defined( 'WP_LOAD_IMPORTERS' ) ) {
161
 
162
  include_once( plugin_dir_path( __FILE__ ) . 'inc/class.Nav_Menu_Roles_Import.php');
163
  // Register the custom importer we've created.
164
  $roles_import = new Nav_Menu_Roles_Import();
165
 
166
+ register_importer( 'nav_menu_roles', __( 'Nav Menu Roles', 'nav-menu-roles' ), sprintf( __( 'Import %snav menu roles%s and other menu item meta skipped by the default importer', 'nav-menu-roles' ), '<strong>', '</strong>' ), array( $roles_import, 'dispatch' ) );
167
 
168
  }
169
 
171
 
172
  /**
173
  * Make Plugin Translation-ready
174
+ *
175
  * @since 1.0
176
  */
 
177
  public function load_text_domain() {
178
  load_plugin_textdomain( 'nav-menu-roles', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
179
  }
181
 
182
  /**
183
  * Display a Notice if plugin conflicts with another
184
+ *
185
  * @since 1.5
186
  * @deprecated will removed in 2.0
187
  */
192
 
193
  /**
194
  * Allow the notice to be dismissable
195
+ *
196
  * @since 1.6
197
  * @deprecated will removed in 2.0
198
  */
202
 
203
  /**
204
  * Delete the transient when a plugin is activated or deactivated
205
+ *
206
  * @since 1.5
207
  * @deprecated will removed in 2.0
208
  */
214
 
215
  /**
216
  * Add docu link
217
+ *
218
+ * @since 1.7.3
219
  * @param array $plugin_meta
220
  * @param string $plugin_file
 
221
  */
222
  public function add_action_links( $plugin_meta, $plugin_file ) {
223
  if( $plugin_file == plugin_basename(__FILE__) ){
230
 
231
  /**
232
  * Override the Admin Menu Walker
233
+ *
234
  * @since 1.0
235
  */
236
  public function edit_nav_menu_walker( $walker ) {
237
  if( ! class_exists( 'Walker_Nav_Menu_Edit_Roles' ) ){
238
  global $wp_version;
239
  if ( version_compare( $wp_version, '4.7', '>=' ) ){
240
+ require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles_4.7.php' );
241
  } else if ( version_compare( $wp_version, '4.5', '>=' ) ){
242
+ require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles_4.5.php' );
243
  } else {
244
+ require_once( plugin_dir_path( __FILE__ ) . 'inc/class.Walker_Nav_Menu_Edit_Roles.php' );
245
  }
246
  }
247
  return 'Walker_Nav_Menu_Edit_Roles';
266
  */
267
  $display_roles = apply_filters( 'nav_menu_roles', $wp_roles->role_names, $item );
268
 
 
269
  /**
270
  * If no roles are being used, don't display the role selection radio buttons at all.
271
  * Unless something deliberately removes the WordPress roles from this list, nothing will
280
  /* Get the roles saved for the post. */
281
  $roles = get_post_meta( $item->ID, '_nav_menu_role', true );
282
 
283
+ // By default nothing is checked (will match "everyone" radio).
284
  $logged_in_out = '';
285
 
286
+ // Specific roles are saved as an array, so "in" or an array equals "in" is checked.
287
  if( is_array( $roles ) || $roles == 'in' ){
288
  $logged_in_out = 'in';
289
  } else if ( $roles == 'out' ){
290
  $logged_in_out = 'out';
291
  }
292
 
293
+ // The specific roles to check.
294
  $checked_roles = is_array( $roles ) ? $roles : false;
295
 
296
+ // Whether to display the role checkboxes.
297
  $hidden = $logged_in_out == 'in' ? '' : 'display: none;';
298
 
299
  ?>
363
 
364
  /**
365
  * Save the roles as menu item meta
366
+ *
367
  * @since 1.4
368
+ * @return null
369
  */
370
  public function enqueue_scripts( $hook ){
371
  if ( $hook == 'nav-menus.php' ){
376
 
377
  /**
378
  * Save the roles as menu item meta
379
+ *
380
  * @since 1.0
381
+ * @return string
382
  */
383
  public function nav_update( $menu_id, $menu_item_db_id ) {
384
  global $wp_roles;
385
 
386
  $allowed_roles = apply_filters( 'nav_menu_roles', $wp_roles->role_names );
387
 
388
+ // Verify this came from our screen and with proper authorization.
389
  if ( ! isset( $_POST['nav-menu-role-nonce'] ) || ! wp_verify_nonce( $_POST['nav-menu-role-nonce'], 'nav-menu-nonce-name' ) ){
390
  return;
391
  }
396
 
397
  $custom_roles = array();
398
 
399
+ // Only save allowed roles.
400
  foreach( (array) $_POST['nav-menu-role'][$menu_item_db_id] as $role ) {
401
  if ( array_key_exists ( $role, $allowed_roles ) ) {
402
  $custom_roles[] = $role;
419
  /**
420
  * Adds value of new field to $item object
421
  * is be passed to Walker_Nav_Menu_Edit_Custom
422
+ *
423
  * @since 1.0
424
  */
425
  public function setup_nav_item( $menu_item ) {
426
 
427
+ if( is_object( $menu_item ) && isset( $menu_item->ID ) ) {
428
+
429
+ $roles = get_post_meta( $menu_item->ID, '_nav_menu_role', true );
430
 
431
+ if ( ! empty( $roles ) ) {
432
+ $menu_item->roles = $roles;
433
+ }
434
  }
435
  return $menu_item;
436
  }
442
  *
443
  * @since 1.2
444
  *
445
+ * @param WP_Post[] array of Nav Menu Post objects
446
+ *
447
  * Multisite compatibility added in 1.9.0
448
  * by @open-dsi https://www.open-dsi.fr/ with props to @fiech
449
  */
453
 
454
  if( ! empty( $items ) ) {
455
 
456
+ // Iterate over the items to search and destroy.
457
  foreach ( $items as $key => $item ) {
458
 
459
  $visible = true;
460
 
461
+ // Hide any item that is the child of a hidden item.
462
+ if( isset( $item->menu_item_parent ) && in_array( $item->menu_item_parent, $hide_children_of ) ){
463
  $visible = false;
 
464
  }
465
 
466
+ // Check any item that has NMR roles set.
467
  if( $visible && isset( $item->roles ) ) {
468
 
469
+ // Check all logged in, all logged out, or role.
470
  switch( $item->roles ) {
471
  case 'in' :
472
  /**
505
 
506
  }
507
 
508
+ /*
509
+ * Filter: nav_menu_roles_item_visibility
510
+ * Add filter to work with plugins that don't use traditional roles
511
+ *
512
+ * @param bool $visible
513
+ * @param object $item
514
+ */
515
  $visible = apply_filters( 'nav_menu_roles_item_visibility', $visible, $item );
516
 
517
+ // Unset non-visible item.
518
  if ( ! $visible ) {
519
+ if( isset( $item->ID ) ) {
520
+ $hide_children_of[] = $item->ID; // Store ID of item to hide it's children.
521
+ }
522
  unset( $items[$key] ) ;
523
  }
524
 
539
  public function maybe_upgrade() {
540
  $db_version = get_option( 'nav_menu_roles_db_version', false );
541
 
542
+ // 1.7.7 upgrade: changed the debug notice so the old transient is invalid.
543
  if ( $db_version === false || version_compare( '1.7.7', $db_version, '<' ) ) {
544
  update_option( 'nav_menu_roles_db_version', self::VERSION );
545
  }
551
 
552
 
553
  /**
554
+ * Launch the whole plugin
555
  * Returns the main instance of Nav Menu Roles to prevent the need to use globals.
556
  *
557
  * @since 1.5
readme.txt CHANGED
@@ -4,8 +4,8 @@ Contributors: helgatheviking
4
  Donate link: https://www.youcaring.com/wnt-residency
5
  Tags: menu, menus, nav menu, nav menus
6
  Requires at least: 4.5.0
7
- Tested up to: 4.8.3
8
- Stable tag: 1.9.2
9
  License: GPLv3
10
 
11
  Hide custom menu items based on user roles. PLEASE READ THE FAQ IF YOU ARE NOT SEEING THE SETTINGS.
@@ -136,6 +136,8 @@ Here's an example where I've added a new pseudo role, creatively called "new-rol
136
 
137
  = Adding a new "role" =
138
 
 
 
139
  `
140
  /*
141
  * Add custom roles to Nav Menu Roles menu list
@@ -176,6 +178,34 @@ add_filter( 'nav_menu_roles_item_visibility', 'kia_item_visibility', 10, 2 );
176
 
177
  Note that you have to generate your own if/then logic. I can't provide free support for custom integration with another plugin. You may [contact me](http://kathyisawesome.com/contact) to discuss hiring me, or I would suggest using a plugin that supports WordPress' roles, such as Justin Tadlock's [Members](http://wordpress.org/plugins/members).
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  = The menu exploded? Why are all my pages displaying for logged out users? =
180
 
181
  If every item in your menu is configured to display to logged in users (either all logged in users, or by specific role), then when a logged out visitor comes to your site there are no items in the menu to display. `wp_nav_menu()` will then try check its `fallback_cb` argument... which defaults to `wp_page_menu`.
@@ -208,6 +238,9 @@ Yes, but manually. WPML developers have informed me that the meta data for nav m
208
 
209
  == Changelog ==
210
 
 
 
 
211
  = 1.9.2 =
212
  * Include a !empty() check on menu $items
213
  * Update donation link
4
  Donate link: https://www.youcaring.com/wnt-residency
5
  Tags: menu, menus, nav menu, nav menus
6
  Requires at least: 4.5.0
7
+ Tested up to: 5.0.2
8
+ Stable tag: 1.9.3
9
  License: GPLv3
10
 
11
  Hide custom menu items based on user roles. PLEASE READ THE FAQ IF YOU ARE NOT SEEING THE SETTINGS.
136
 
137
  = Adding a new "role" =
138
 
139
+ The roles in NMR are filterable distinct from the global `$wp_roles`. This allows for compatibility to be added between plugins that don't use the core roles to determine access, like some membership plugins.
140
+
141
  `
142
  /*
143
  * Add custom roles to Nav Menu Roles menu list
178
 
179
  Note that you have to generate your own if/then logic. I can't provide free support for custom integration with another plugin. You may [contact me](http://kathyisawesome.com/contact) to discuss hiring me, or I would suggest using a plugin that supports WordPress' roles, such as Justin Tadlock's [Members](http://wordpress.org/plugins/members).
180
 
181
+
182
+ = Existing Compatibility Plugins =
183
+
184
+ 1. [Wishlists Memberships](https://github.com/helgatheviking/nav-menu-roles-wishlists-memberships)
185
+ 2. [WooCommerce Memberships](https://github.com/helgatheviking/nav-menu-roles-woocommerce-memberships)
186
+
187
+ If your membership plugin is not listed here, you may be able to use the above bridge plugins as a template. Scroll down to the bottom of the main plugin file and you will see a section for "Helper Functions". If you modify the 3 wrapper functions according to your membership plugin's logic, the rest of the plugin should handle the integration with Nav Menu Roles.
188
+
189
+ = Sort the roles alphabetically =
190
+
191
+ Add the following snippet to your theme's `functions.php` file:
192
+
193
+ `
194
+ /*
195
+ * Sort the NMR roles
196
+ * @param: $roles an array of all available roles with ID=>Name
197
+ * @return: array
198
+ */
199
+ function kia_sort_roles( $roles ){
200
+ if( is_admin() ) {
201
+ $array_lowercase = array_map( 'strtolower', $roles );
202
+ array_multisort( $array_lowercase, SORT_ASC, SORT_STRING, $roles );
203
+ return $roles;
204
+ }
205
+ }
206
+ add_filter( 'nav_menu_roles', 'kia_sort_roles' );
207
+ `
208
+
209
  = The menu exploded? Why are all my pages displaying for logged out users? =
210
 
211
  If every item in your menu is configured to display to logged in users (either all logged in users, or by specific role), then when a logged out visitor comes to your site there are no items in the menu to display. `wp_nav_menu()` will then try check its `fallback_cb` argument... which defaults to `wp_page_menu`.
238
 
239
  == Changelog ==
240
 
241
+ = 1.9.3 =
242
+ * Check all object properties exist before accessing. Resolves PHP notices for custom menu items.
243
+
244
  = 1.9.2 =
245
  * Include a !empty() check on menu $items
246
  * Update donation link