Skip to content

Proposal to Add Membership-Based Menu Item Visibility in PMPro Nav Menus #27

@mywebhero

Description

@mywebhero

Certainly! Here's the message styled for a GitHub discussion:


Hi everyone,

I've been working on extending the functionality of the PMPro Nav Menus plugin to allow menu items to be dynamically hidden based on the user's membership level. This feature could be useful for sites where certain pages or sections are restricted to specific membership levels, and it would be beneficial to hide inaccessible menu items automatically.

Proposed Code

Here’s the code I’ve implemented:

function pmpronm_modify_nav_menu_args( $args ) {
    // Ensure PMPro is active
    if (!function_exists('pmpro_hasMembershipLevel')) {
        return $args;
    }
    
    // If the user is not logged in, return the args as is
    if (!is_user_logged_in()) {
        return $args;
    }

    // Get current user's level ids
    global $current_user;
    $levels = pmpro_getMembershipLevelsForUser($current_user->ID);
    $level_ids = wp_list_pluck($levels, 'id');
    $found_menu = false;

    // For logged-in non-members...
    if (is_user_logged_in() && empty($level_ids)) {
        // Give non-member menu.
        if (has_nav_menu("pmpro-non-members-" . $args['theme_location'])) {
            $args['theme_location'] = "pmpro-non-members-" . $args['theme_location'];
            $found_menu = true;
        }
    }

    // Find menu for membership ID, or give membership menu...
    if (!$found_menu && !empty($level_ids)) {
        // Get levels in priority order.
        $prioritized_levels = apply_filters('pmpronm_prioritize_levels', array());

        // Add levels that are not prioritized.
        $prioritized_levels = array_merge($prioritized_levels, array_diff($level_ids, $prioritized_levels));
        foreach ($prioritized_levels as $prioritized_level_id) {
            if (in_array($prioritized_level_id, $level_ids) && has_nav_menu("members-" . $prioritized_level_id . "-" . $args['theme_location'])) {
                $args['theme_location'] = "members-" . $prioritized_level_id . "-" . $args['theme_location'];
                $found_menu = true;
                break;
            }
        }

        if (!$found_menu && has_nav_menu('members-' . $args['theme_location'])) {
            $args['theme_location'] = 'members-' . $args['theme_location'];
        }
    }

    // Apply filter to remove inaccessible items
    add_filter('wp_nav_menu_objects', function ($items) use ($level_ids) {
        foreach ($items as $key => $item) {
            if (pmpro_is_menu_item_restricted($item, $level_ids)) {
                unset($items[$key]); // Remove the item if the user doesn't have access
            }
        }
        return $items;
    }, 10, 1);

    return $args;
}

// Function to determine if a menu item is restricted
function pmpro_is_menu_item_restricted($item, $user_level_ids) {
    if ($item->object == 'page' || $item->object == 'post') {
        $has_access = pmpro_has_membership_access($item->object_id);
        return !$has_access;
    }
    return false;
}

What It Does

  • Menu Selection: Modifies the menu displayed based on the user's membership level.
  • Hiding Inaccessible Items: Filters out individual menu items that the user does not have access to based on their membership level.

Feedback Requested

I believe this feature could be beneficial for users who want to automatically hide inaccessible menu items without manually configuring each item. Before spending more time refining and optimizing the code, I’d like to gauge interest from the community:

  • Is this functionality something you would find useful?
  • Would you support integrating this into the main plugin?
  • Are there specific features or configurations you think should be included?

If there’s enough interest, I’m happy to invest more time into polishing this feature and making it available as part of the PMPro Nav Menus plugin.

Looking forward to your feedback!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions