skip to Main Content

On my primary wp nav, I have a menu item named ‘Research’ which i want to only be shown for Researchers in wordpress.

Researchers will be defined by a user meta field called wpum_relationship_to_lib which is a multiple choices field including options like: researcher, student, employee and so on.

It is important that researcher must be one of the options the user choses to access that menu and that wpum_relationship_to_lib does not define a WordPress role.

All menus are primary. Also, I need the menu to be hidden even before login. See my code below which is not restricting menu properly.

function restrict_menu_to_researchers($items, $args) {
  
  // Check if the menu is assigned to the desired location
  if ($args->theme_location === 'primary') {

    // Check if the user is logged in
    if (is_user_logged_in()) {

      $user_id = get_current_user_id();
      $relationship_values = get_user_meta($user_id, 'wpum_relationship_to_lib', true);
            
      // Check if the user is the "researcher" 
      if (is_array($relationship_values) && in_array('researcher', $relationship_values)) {

        // Allow the menu for researchers
        return $items; 

      } else {
        foreach ($items as $key => $item) {
          if ($item->title == 'Research') {
            // Hide the "Research" menu for non-researchers
            unset($items[$key]); 
          }
        } 
      }
    } else {
      foreach ($items as $key => $item) {
        if ($item->title == 'Research') {
          // Hide the "Research" menu for non-logged-in users
          unset($items[$key]);
        }
      }
    }
  }
  return $items;
}
add_filter('wp_nav_menu_objects', 'restrict_menu_to_researchers', 10, 2);

2

Answers


  1. Actually ignore my comment, using $item->title seems to work as well.

    I think your looping is wrong in yours. Try this version.

    https://developer.wordpress.org/reference/hooks/wp_nav_menu_objects/

    See comments in php so you understand what is going on.

    function restrict_menu_to_researchers( $menu_objects, $args )
    {
    
        // bail early if not on primary menu
        if ('primary' !== $args->theme_location) {
            return $menu_objects;
        }
    
        // if user is logged in
        if (is_user_logged_in()) {
    
            // get relationship array
            $relationship_array = (array)get_user_meta(get_current_user_id(), 'wpum_relationship_to_lib', true);
            
            // foreach menu as key > menu object
            foreach ($menu_objects as $key => $menu_object) {
    
                // if menu object title is Research and is not in relationship array
                if ( $menu_object->title === 'Research' && !in_array($menu_object->title, $relationship_array ) ) {
    
                    // then restrict the menu object item
                    unset( $menu_objects[$key] );
                    
                }
    
            }
    
        }
    
        // return menu objects
        return $menu_objects;
    
    }
    
    add_filter('wp_nav_menu_objects', 'restrict_menu_to_researchers', 10, 2 );
    
    Login or Signup to reply.
  2. The code provided is mostly correct. However, there is a small issue in the conditional statement when checking the user’s relationship values. I updated the code to ensure that the "Research" menu item is only shown to users who have selected "researcher" as one of their relationship values in the wpum_relationship_to_lib meta field. It also hides the "Research" menu for non-logged-in users. I did not tested the code, so any comment is welcome.
    The code of #joshmoto is working, but in the foreach loop, the condition !in_array($menu_object->title, $relationship_array) checks if the menu object title is not in the relationship array. From what i understood from the question, you want to check if the value "researcher" is in the relationship array. Therefore, you should update the condition to in_array(‘researcher’, $relationship_array).

    function restrict_menu_to_researchers($items, $args) {
      // Check if the menu is assigned to the desired location
      if ($args->theme_location === 'primary') {
        // Check if the user is logged in
        if (is_user_logged_in()) {
          $user_id = get_current_user_id();
          $relationship_values = get_user_meta($user_id, 'wpum_relationship_to_lib', true);
          
          // Check if the user has selected "researcher" as one of their relationship values
          if (is_array($relationship_values) && in_array('researcher', $relationship_values, true)) {
            // Allow the menu for researchers
            return $items;
          } else {
            // Hide the "Research" menu for non-researchers
            foreach ($items as $key => $item) {
              if ($item->title === 'Research') {
                unset($items[$key]);
              }
            }
          }
        } else {
          // Hide the "Research" menu for non-logged-in users
          foreach ($items as $key => $item) {
            if ($item->title === 'Research') {
              unset($items[$key]);
            }
          }
        }
      }
      return $items;
    }
    add_filter('wp_nav_menu_objects', 'restrict_menu_to_researchers', 10, 2);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search