/**
 * Adds a navigation item to the main navigation array used in BuddyPress themes.
 *
 * @package BuddyPress Core
 * @global object $bp Global BuddyPress settings object
 */
function bp_core_new_nav_item($args = '')
{
    global $bp;
    $defaults = array('name' => false, 'slug' => false, 'item_css_id' => false, 'show_for_displayed_user' => true, 'site_admin_only' => false, 'position' => 99, 'screen_function' => false, 'default_subnav_slug' => false);
    $r = nxt_parse_args($args, $defaults);
    extract($r, EXTR_SKIP);
    // If we don't have the required info we need, don't create this subnav item
    if (empty($name) || empty($slug)) {
        return false;
    }
    // If this is for site admins only and the user is not one, don't create the subnav item
    if ($site_admin_only && !is_super_admin()) {
        return false;
    }
    if (empty($item_css_id)) {
        $item_css_id = $slug;
    }
    $bp->bp_nav[$slug] = array('name' => $name, 'slug' => $slug, 'link' => $bp->loggedin_user->domain . $slug . '/', 'css_id' => $item_css_id, 'show_for_displayed_user' => $show_for_displayed_user, 'position' => $position, 'screen_function' => &$screen_function);
    /***
     * If this nav item is hidden for the displayed user, and
     * the logged in user is not the displayed user
     * looking at their own profile, don't create the nav item.
     */
    if (!$show_for_displayed_user && !bp_user_has_access()) {
        return false;
    }
    /***
     * If the nav item is visible, we are not viewing a user, and this is a root
     * component, don't attach the default subnav function so we can display a
     * directory or something else.
     */
    if (-1 != $position && bp_is_root_component($slug) && !bp_displayed_user_id()) {
        return;
    }
    // Look for current component
    if (bp_is_current_component($slug) && !bp_current_action()) {
        if (!is_object($screen_function[0])) {
            add_action('bp_screens', $screen_function);
        } else {
            add_action('bp_screens', array(&$screen_function[0], $screen_function[1]), 3);
        }
        if (!empty($default_subnav_slug)) {
            $bp->current_action = apply_filters('bp_default_component_subnav', $default_subnav_slug, $r);
        }
        // Look for current item
    } elseif (bp_is_current_item($slug) && !bp_current_action()) {
        if (!is_object($screen_function[0])) {
            add_action('bp_screens', $screen_function);
        } else {
            add_action('bp_screens', array(&$screen_function[0], $screen_function[1]), 3);
        }
        if (!empty($default_subnav_slug)) {
            $bp->current_action = apply_filters('bp_default_component_subnav', $default_subnav_slug, $r);
        }
    }
    do_action('bp_core_new_nav_item', $r, $args, $defaults);
}
Example #2
0
/**
 * Register a screen function, whether or not a related subnav link exists.
 *
 * @param array|string $args {
 *     Array describing the new subnav item.
 *     @type string   $slug              Unique URL slug for the subnav item.
 *     @type string   $parent_slug       Slug of the top-level nav item under which the
 *                                       new subnav item should be added.
 *     @type string   $parent_url        URL of the parent nav item.
 *     @type bool     $user_has_access   Optional. True if the logged-in user has access to the
 *                                       subnav item, otherwise false. Can be set dynamically
 *                                       when registering the subnav; eg, use bp_is_my_profile()
 *                                       to restrict access to profile owners only. Default: true.
 *     @type bool     $site_admin_only   Optional. Whether the nav item should be visible
 *                                       only to site admins (those with the 'bp_moderate' cap).
 *                                       Default: false.
 *     @type int      $position          Optional. Numerical index specifying where the item
 *                                       should appear in the subnav array. Default: 90.
 *     @type callable $screen_function   The callback function that will run
 *                                       when the nav item is clicked.
 *     @type string   $link              Optional. The URL that the subnav item should point to.
 *                                       Defaults to a value generated from the $parent_url + $slug.
 *     @type bool     $show_in_admin_bar Optional. Whether the nav item should be added into
 *                                       the group's "Edit" Admin Bar menu for group admins.
 *                                       Default: false.
 * }
 *
 * @return bool|null Returns false on failure.
 */
function bp_core_register_subnav_screen_function($args = '')
{
    $bp = buddypress();
    $r = wp_parse_args($args, array('slug' => false, 'parent_slug' => false, 'user_has_access' => true, 'no_access_url' => '', 'site_admin_only' => false, 'screen_function' => false));
    /**
     * Hook the screen function for the added subnav item. But this only needs to
     * be done if this subnav item is the current view, and the user has access to the
     * subnav item. We figure out whether we're currently viewing this subnav by
     * checking the following two conditions:
     *   (1) Either:
     *	     (a) the parent slug matches the current_component, or
     *	     (b) the parent slug matches the current_item
     *   (2) And either:
     *	     (a) the current_action matches $slug, or
     *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
     *	     and this subnav item is the default for the parent item (which we check by
     *	     comparing this subnav item's screen function with the screen function of the
     *	     parent nav item in $bp->bp_nav). This condition only arises when viewing a
     *	     user, since groups should always have an action set.
     */
    // If we *don't* meet condition (1), return
    if (!bp_is_current_component($r['parent_slug']) && !bp_is_current_item($r['parent_slug'])) {
        return;
    }
    // If we *do* meet condition (2), then the added subnav item is currently being requested
    if (bp_current_action() && bp_is_current_action($r['slug']) || bp_is_user() && !bp_current_action() && $r['screen_function'] == $bp->bp_nav[$r['parent_slug']]['screen_function']) {
        // If this is for site admins only and the user is not one, don't create the subnav item
        if (!empty($r['site_admin_only']) && !bp_current_user_can('bp_moderate')) {
            return false;
        }
        $hooked = bp_core_maybe_hook_new_subnav_screen_function($r);
        // If redirect args have been returned, perform the redirect now
        if (!empty($hooked['status']) && 'failure' === $hooked['status'] && isset($hooked['redirect_args'])) {
            bp_core_no_access($hooked['redirect_args']);
        }
    }
}
/**
 * Add a subnav item to the BuddyPress navigation.
 *
 * @global BuddyPress $bp The one true BuddyPress instance.
 *
 * @param array $args {
 *     Array describing the new subnav item.
 *     @type string $name Display name for the subnav item.
 *     @type string $slug Unique URL slug for the subnav item.
 *     @type string $parent_slug Slug of the top-level nav item under which the
 *           new subnav item should be added.
 *     @type string $parent_url URL of the parent nav item.
 *     @type bool|string $item_css_id Optional. 'id' attribute for the nav
 *           item. Default: the value of $slug.
 *     @type bool $user_has_access Optional. True if the logged-in user has
 *           access to the subnav item, otherwise false. Can be set dynamically
 *           when registering the subnav; eg, use bp_is_my_profile() to restrict
 *           access to profile owners only. Default: true.
 *     @type bool $site_admin_only Optional. Whether the nav item should be
 *           visible only to site admins (those with the 'bp_moderate' cap).
 *           Default: false.
 *     @type int $position Optional. Numerical index specifying where the item
 *           should appear in the subnav array. Default: 90.
 *     @type callable $screen_function The callback function that will run
 *           when the nav item is clicked.
 *     @type string $link Optional. The URL that the subnav item should point
 *           to. Defaults to a value generated from the $parent_url + $slug.
 * }
 * @return bool|null Returns false on failure.
 */
function bp_core_new_subnav_item($args = '')
{
    global $bp;
    $defaults = array('name' => false, 'slug' => false, 'parent_slug' => false, 'parent_url' => false, 'item_css_id' => false, 'user_has_access' => true, 'site_admin_only' => false, 'position' => 90, 'screen_function' => false, 'link' => '');
    $r = wp_parse_args($args, $defaults);
    extract($r, EXTR_SKIP);
    // If we don't have the required info we need, don't create this subnav item
    if (empty($name) || empty($slug) || empty($parent_slug) || empty($parent_url) || empty($screen_function)) {
        return false;
    }
    // Link was not forced, so create one
    if (empty($link)) {
        $link = $parent_url . $slug;
        // If this sub item is the default for its parent, skip the slug
        if (!empty($bp->bp_nav[$parent_slug]['default_subnav_slug']) && $slug == $bp->bp_nav[$parent_slug]['default_subnav_slug']) {
            $link = $parent_url;
        }
    }
    // If this is for site admins only and the user is not one, don't create the subnav item
    if (!empty($site_admin_only) && !bp_current_user_can('bp_moderate')) {
        return false;
    }
    if (empty($item_css_id)) {
        $item_css_id = $slug;
    }
    $bp->bp_options_nav[$parent_slug][$slug] = array('name' => $name, 'link' => trailingslashit($link), 'slug' => $slug, 'css_id' => $item_css_id, 'position' => $position, 'user_has_access' => $user_has_access, 'screen_function' => &$screen_function);
    /**
     * The last step is to hook the screen function for the added subnav item. But this only
     * needs to be done if this subnav item is the current view, and the user has access to the
     * subnav item. We figure out whether we're currently viewing this subnav by checking the
     * following two conditions:
     *   (1) Either:
     *	     (a) the parent slug matches the current_component, or
     *	     (b) the parent slug matches the current_item
     *   (2) And either:
     *	     (a) the current_action matches $slug, or
     *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
     *	     and this subnav item is the default for the parent item (which we check by
     *	     comparing this subnav item's screen function with the screen function of the
     *	     parent nav item in $bp->bp_nav). This condition only arises when viewing a
     *	     user, since groups should always have an action set.
     */
    // If we *don't* meet condition (1), return
    if (!bp_is_current_component($parent_slug) && !bp_is_current_item($parent_slug)) {
        return;
    }
    // If we *do* meet condition (2), then the added subnav item is currently being requested
    if (bp_current_action() && bp_is_current_action($slug) || bp_is_user() && !bp_current_action() && $screen_function == $bp->bp_nav[$parent_slug]['screen_function']) {
        // Before hooking the screen function, check user access
        if (!empty($user_has_access)) {
            // Add our screen hook if screen function is callable
            if (is_callable($screen_function)) {
                add_action('bp_screens', $screen_function, 3);
            }
        } else {
            // When the content is off-limits, we handle the situation
            // differently depending on whether the current user is logged in
            if (is_user_logged_in()) {
                if (!bp_is_my_profile() && empty($bp->bp_nav[$bp->default_component]['show_for_displayed_user'])) {
                    // This covers the edge case where the default component is
                    // a non-public tab, like 'messages'
                    if (bp_is_active('activity') && isset($bp->pages->activity)) {
                        $redirect_to = trailingslashit(bp_displayed_user_domain() . bp_get_activity_slug());
                    } else {
                        $redirect_to = trailingslashit(bp_displayed_user_domain() . ('xprofile' == $bp->profile->id ? 'profile' : $bp->profile->id));
                    }
                    $message = '';
                } else {
                    $message = __('You do not have access to this page.', 'buddypress');
                    $redirect_to = bp_displayed_user_domain();
                }
                // Off-limits to this user. Throw an error and redirect to the displayed user's domain
                bp_core_no_access(array('message' => $message, 'root' => $redirect_to, 'redirect' => false));
                // Not logged in. Allow the user to log in, and attempt to redirect
            } else {
                bp_core_no_access();
            }
        }
    }
}
Example #4
0
/**
 * Add a subnav item to the BuddyPress navigation.
 *
 * @param array $args {
 *     Array describing the new subnav item.
 *     @type string $name Display name for the subnav item.
 *     @type string $slug Unique URL slug for the subnav item.
 *     @type string $parent_slug Slug of the top-level nav item under which the
 *           new subnav item should be added.
 *     @type string $parent_url URL of the parent nav item.
 *     @type bool|string $item_css_id Optional. 'id' attribute for the nav
 *           item. Default: the value of $slug.
 *     @type bool $user_has_access Optional. True if the logged-in user has
 *           access to the subnav item, otherwise false. Can be set dynamically
 *           when registering the subnav; eg, use bp_is_my_profile() to restrict
 *           access to profile owners only. Default: true.
 *     @type bool $site_admin_only Optional. Whether the nav item should be
 *           visible only to site admins (those with the 'bp_moderate' cap).
 *           Default: false.
 *     @type int $position Optional. Numerical index specifying where the item
 *           should appear in the subnav array. Default: 90.
 *     @type callable $screen_function The callback function that will run
 *           when the nav item is clicked.
 *     @type string $link Optional. The URL that the subnav item should point
 *           to. Defaults to a value generated from the $parent_url + $slug.
 *     @type bool $show_in_admin_bar Optional. Whether the nav item should be
 *           added into the group's "Edit" Admin Bar menu for group admins.
 *           Default: false.
 * }
 * @return bool|null Returns false on failure.
 */
function bp_core_new_subnav_item($args = '')
{
    $bp = buddypress();
    $r = wp_parse_args($args, array('name' => false, 'slug' => false, 'parent_slug' => false, 'parent_url' => false, 'item_css_id' => false, 'user_has_access' => true, 'no_access_url' => '', 'site_admin_only' => false, 'position' => 90, 'screen_function' => false, 'link' => '', 'show_in_admin_bar' => false));
    extract($r, EXTR_SKIP);
    // If we don't have the required info we need, don't create this subnav item
    if (empty($name) || empty($slug) || empty($parent_slug) || empty($parent_url) || empty($screen_function)) {
        return false;
    }
    // Link was not forced, so create one
    if (empty($link)) {
        $link = trailingslashit($parent_url . $slug);
        // If this sub item is the default for its parent, skip the slug
        if (!empty($bp->bp_nav[$parent_slug]['default_subnav_slug']) && $slug == $bp->bp_nav[$parent_slug]['default_subnav_slug']) {
            $link = trailingslashit($parent_url);
        }
    }
    // If this is for site admins only and the user is not one, don't create the subnav item
    if (!empty($site_admin_only) && !bp_current_user_can('bp_moderate')) {
        return false;
    }
    if (empty($item_css_id)) {
        $item_css_id = $slug;
    }
    $subnav_item = array('name' => $name, 'link' => $link, 'slug' => $slug, 'css_id' => $item_css_id, 'position' => $position, 'user_has_access' => $user_has_access, 'no_access_url' => $no_access_url, 'screen_function' => &$screen_function, 'show_in_admin_bar' => (bool) $r['show_in_admin_bar']);
    $bp->bp_options_nav[$parent_slug][$slug] = $subnav_item;
    /**
     * The last step is to hook the screen function for the added subnav item. But this only
     * needs to be done if this subnav item is the current view, and the user has access to the
     * subnav item. We figure out whether we're currently viewing this subnav by checking the
     * following two conditions:
     *   (1) Either:
     *	     (a) the parent slug matches the current_component, or
     *	     (b) the parent slug matches the current_item
     *   (2) And either:
     *	     (a) the current_action matches $slug, or
     *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
     *	     and this subnav item is the default for the parent item (which we check by
     *	     comparing this subnav item's screen function with the screen function of the
     *	     parent nav item in $bp->bp_nav). This condition only arises when viewing a
     *	     user, since groups should always have an action set.
     */
    // If we *don't* meet condition (1), return
    if (!bp_is_current_component($parent_slug) && !bp_is_current_item($parent_slug)) {
        return;
    }
    // If we *do* meet condition (2), then the added subnav item is currently being requested
    if (bp_current_action() && bp_is_current_action($slug) || bp_is_user() && !bp_current_action() && $screen_function == $bp->bp_nav[$parent_slug]['screen_function']) {
        $hooked = bp_core_maybe_hook_new_subnav_screen_function($subnav_item);
        // If redirect args have been returned, perform the redirect now
        if (!empty($hooked['status']) && 'failure' === $hooked['status'] && isset($hooked['redirect_args'])) {
            bp_core_no_access($hooked['redirect_args']);
        }
    }
}
/**
 * Adds a navigation item to the main navigation array used in BuddyPress themes.
 *
 * @package BuddyPress Core
 * @global object $bp Global BuddyPress settings object
 */
function bp_core_new_nav_item($args = '')
{
    global $bp;
    $defaults = array('name' => false, 'slug' => false, 'item_css_id' => false, 'show_for_displayed_user' => true, 'site_admin_only' => false, 'position' => 99, 'screen_function' => false, 'default_subnav_slug' => false);
    $r = wp_parse_args($args, $defaults);
    extract($r, EXTR_SKIP);
    // If we don't have the required info we need, don't create this subnav item
    if (empty($name) || empty($slug)) {
        return false;
    }
    // If this is for site admins only and the user is not one, don't create the subnav item
    if ($site_admin_only && !bp_current_user_can('bp_moderate')) {
        return false;
    }
    if (empty($item_css_id)) {
        $item_css_id = $slug;
    }
    $bp->bp_nav[$slug] = array('name' => $name, 'slug' => $slug, 'link' => $bp->loggedin_user->domain . $slug . '/', 'css_id' => $item_css_id, 'show_for_displayed_user' => $show_for_displayed_user, 'position' => $position, 'screen_function' => &$screen_function);
    /***
     * If this nav item is hidden for the displayed user, and
     * the logged in user is not the displayed user
     * looking at their own profile, don't create the nav item.
     */
    if (!$show_for_displayed_user && !bp_user_has_access()) {
        return false;
    }
    /***
     * If the nav item is visible, we are not viewing a user, and this is a root
     * component, don't attach the default subnav function so we can display a
     * directory or something else.
     */
    if (-1 != $position && bp_is_root_component($slug) && !bp_displayed_user_id()) {
        return;
    }
    // Look for current component
    if (bp_is_current_component($slug) && !bp_current_action()) {
        if (!is_object($screen_function[0])) {
            add_action('bp_screens', $screen_function);
        } else {
            add_action('bp_screens', array(&$screen_function[0], $screen_function[1]), 3);
        }
        if (!empty($default_subnav_slug)) {
            /**
             * BuddyPress will attempt to resolve to the most specific URL possible,
             * to avoid search-engine-unfriendly content reduplication. Filter
             * bp_guarantee_unique_uris (and return false) to avoid this behavior
             */
            if (apply_filters('bp_guarantee_unique_uris', true)) {
                bp_core_redirect(bp_displayed_user_domain() . $slug . '/' . apply_filters('bp_default_component_subnav', $default_subnav_slug, $r));
            } else {
                $bp->current_action = apply_filters('bp_default_component_subnav', $default_subnav_slug, $r);
            }
        }
        // Look for current item
    } elseif (bp_is_current_item($slug) && !bp_current_action()) {
        if (!is_object($screen_function[0])) {
            add_action('bp_screens', $screen_function);
        } else {
            add_action('bp_screens', array(&$screen_function[0], $screen_function[1]), 3);
        }
        if (!empty($default_subnav_slug)) {
            /**
             * BuddyPress will attempt to resolve to the most specific URL possible,
             * to avoid search-engine-unfriendly content reduplication. Filter
             * bp_guarantee_unique_uris (and return false) to avoid this behavior
             */
            if (apply_filters('bp_guarantee_unique_uris', true)) {
                bp_core_redirect(bp_get_root_domain() . '/' . bp_get_root_slug(bp_current_component()) . '/' . $slug . '/' . apply_filters('bp_default_component_subnav', $default_subnav_slug, $r));
            } else {
                $bp->current_action = apply_filters('bp_default_component_subnav', $default_subnav_slug, $r);
            }
        }
    }
    do_action('bp_core_new_nav_item', $r, $args, $defaults);
}