Skip to:
Content

BuddyPress.org

Ticket #6534: 6534.2.diff

File 6534.2.diff, 99.4 KB (added by boonebgorges, 7 years ago)
  • src/bp-core/bp-core-buddybar.php

    diff --git src/bp-core/bp-core-buddybar.php src/bp-core/bp-core-buddybar.php
    index 9f1ffb0..63c7a5d 100644
     
    1313defined( 'ABSPATH' ) || exit;
    1414
    1515/**
    16  * Add an item to the main BuddyPress navigation array.
     16 * Add an item to the primary navigation of the specified component.
    1717 *
    1818 * @since 1.1.0
     19 * @since 2.6.0 Introduced the `$component` parameter.
    1920 *
    2021 * @param array|string $args {
    2122 *     Array describing the new nav item.
    defined( 'ABSPATH' ) || exit; 
    3233 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    3334 *                                                item is clicked.
    3435 * }
     36 * @param string       $component                 The component the navigation is attached to. Defaults to 'members'.
    3537 * @return bool|null Returns false on failure.
    3638 */
    37 function bp_core_new_nav_item( $args = '' ) {
     39
     40function bp_core_new_nav_item( $args, $component = 'members' ) {
     41        if ( ! bp_is_active( $component ) ) {
     42                return;
     43        }
    3844
    3945        $defaults = array(
    4046                'name'                    => false, // Display name for the nav item.
    function bp_core_new_nav_item( $args = '' ) { 
    4955
    5056        $r = wp_parse_args( $args, $defaults );
    5157
    52         // First, add the nav item link to the bp_nav array.
    53         $created = bp_core_create_nav_link( $r );
     58        // Validate nav link data.
     59        $nav_item = bp_core_create_nav_link( $r, $component );
    5460
    55         // To mimic the existing behavior, if bp_core_create_nav_link()
    56         // returns false, we make an early exit and don't attempt to register
    57         // the screen function.
    58         if ( false === $created ) {
     61        /*
     62         * To mimic legacy behavior, if bp_core_create_nav_link() returns false, we make
     63         * an early exit and don't attempt to register the screen function.
     64         */
     65        if ( false === $nav_item ) {
    5966                return false;
    6067        }
    6168
    6269        // Then, hook the screen function for the added nav item.
    63         $hooked = bp_core_register_nav_screen_function( $r );
     70        $hooked = bp_core_register_nav_screen_function( $nav_item );
    6471        if ( false === $hooked ){
    6572                return false;
    6673        }
    function bp_core_new_nav_item( $args = '' ) { 
    8188}
    8289
    8390/**
    84  * Add a link to the main BuddyPress navigation array.
     91 * Add a link to the main BuddyPress navigation.
    8592 *
    8693 * @since 2.4.0
     94 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
    8795 *
    8896 * @param array|string $args {
    8997 *     Array describing the new nav item.
    function bp_core_new_nav_item( $args = '' ) { 
    100108 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    101109 *                                                item is clicked.
    102110 * }
    103  * @return bool|null Returns false on failure.
     111 * @param string $component Optional. Component that the nav belongs to.
     112 * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
    104113 */
    105 function bp_core_create_nav_link( $args = '' ) {
     114function bp_core_create_nav_link( $args = '', $component = 'members' ) {
    106115        $bp = buddypress();
    107116
    108117        $defaults = array(
    function bp_core_create_nav_link( $args = '' ) { 
    132141                $r['item_css_id'] = $r['slug'];
    133142        }
    134143
    135         $bp->bp_nav[$r['slug']] = array(
     144        $nav_item = array(
    136145                'name'                    => $r['name'],
    137146                'slug'                    => $r['slug'],
    138147                'link'                    => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ),
    function bp_core_create_nav_link( $args = '' ) { 
    143152                'default_subnav_slug'     => $r['default_subnav_slug']
    144153        );
    145154
     155        // Add the item to the nav.
     156        $retval = buddypress()->{$component}->nav->add_nav( $nav_item );
     157
    146158        /**
    147          * Fires after a link is added to the main BuddyPress navigation array.
     159         * Fires after a link is added to the main BuddyPress nav.
    148160         *
    149161         * @since 2.4.0
    150162         *
    151          * @param array $r        Parsed arguments for the nav item.
    152          * @param array $args     Originally passed in arguments for the nav item.
    153          * @param array $defaults Default arguments for a nav item.
     163         * @param array  $r         Parsed arguments for the nav item.
     164         * @param array  $args      Originally passed in arguments for the nav item.
     165         * @param array  $defaults  Default arguments for a nav item.
     166         * @param string $component Component that the nav belongs to.
    154167         */
    155         do_action( 'bp_core_create_nav_link', $r, $args, $defaults );
     168        do_action( 'bp_core_create_nav_link', $r, $args, $defaults, $component );
     169
     170        return $retval;
    156171}
    157172
    158173/**
    function bp_core_new_nav_default( $args = '' ) { 
    290305
    291306        $r = wp_parse_args( $args, $defaults );
    292307
    293         if ( $function = $bp->bp_nav[$r['parent_slug']]['screen_function'] ) {
     308        // This is specific to Members - it's not available in Groups.
     309        $parent_nav = $bp->members->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     310
     311        if ( ! $parent_nav ) {
     312                return ;
     313        }
     314
     315        $parent_nav = reset( $parent_nav );
     316
     317        if ( ! empty( $parent_nav->screen_function ) ) {
    294318                // Remove our screen hook if screen function is callable.
    295                 if ( is_callable( $function ) ) {
    296                         remove_action( 'bp_screens', $function, 3 );
     319                if ( is_callable( $parent_nav->screen_function ) ) {
     320                        remove_action( 'bp_screens', $parent_nav->screen_function, 3 );
    297321                }
    298322        }
    299323
    300         $bp->bp_nav[$r['parent_slug']]['screen_function'] = &$r['screen_function'];
     324        // Edit the screen function for the parent nav
     325        $bp->members->nav->edit_nav( array(
     326                'screen_function'     => &$r['screen_function'],
     327                'default_subnav_slug' => $r['subnav_slug'],
     328        ), $parent_nav->slug );
    301329
    302         if ( bp_is_current_component( $r['parent_slug'] ) ) {
     330        if ( bp_is_current_component( $parent_nav->slug ) ) {
    303331
    304332                // The only way to tell whether to set the subnav is to peek at the unfiltered_uri
    305333                // Find the component.
    306                 $component_uri_key = array_search( $r['parent_slug'], $bp->unfiltered_uri );
     334                $component_uri_key = array_search( $parent_nav->slug, $bp->unfiltered_uri );
    307335
    308336                if ( false !== $component_uri_key ) {
    309337                        if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
    function bp_core_new_nav_default( $args = '' ) { 
    339367}
    340368
    341369/**
    342  * Sort the navigation menu items.
    343  *
    344  * The sorting is split into a separate function because it can only happen
    345  * after all plugins have had a chance to register their navigation items.
    346  *
    347  * @since 1.0.0
    348  *
    349  * @return bool|null Returns false on failure.
    350  */
    351 function bp_core_sort_nav_items() {
    352         $bp = buddypress();
    353 
    354         if ( empty( $bp->bp_nav ) || ! is_array( $bp->bp_nav ) ) {
    355                 return false;
    356         }
    357 
    358         $temp = array();
    359 
    360         foreach ( (array) $bp->bp_nav as $slug => $nav_item ) {
    361                 if ( empty( $temp[$nav_item['position']] ) ) {
    362                         $temp[$nav_item['position']] = $nav_item;
    363                 } else {
    364                         // Increase numbers here to fit new items in.
    365                         do {
    366                                 $nav_item['position']++;
    367                         } while ( ! empty( $temp[$nav_item['position']] ) );
    368 
    369                         $temp[$nav_item['position']] = $nav_item;
    370                 }
    371         }
    372 
    373         ksort( $temp );
    374         $bp->bp_nav = &$temp;
    375 }
    376 add_action( 'wp_head',    'bp_core_sort_nav_items' );
    377 add_action( 'admin_head', 'bp_core_sort_nav_items' );
    378 
    379 /**
    380  * Add a subnav item to the BuddyPress navigation.
     370 * Add an item to secondary navigation of the specified component.
    381371 *
    382372 * @since 1.1.0
     373 * @since 2.6.0 Introduced the `$component` parameter.
    383374 *
    384375 * @param array|string $args {
    385376 *     Array describing the new subnav item.
    add_action( 'admin_head', 'bp_core_sort_nav_items' ); 
    403394 *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
    404395 *                                          Admin Bar menu for group admins. Default: false.
    405396 * }
     397 * @param string $component The component the navigation is attached to. Defaults to 'members'.
    406398 * @return bool|null Returns false on failure.
    407399 */
    408 function bp_core_new_subnav_item( $args = '' ) {
     400function bp_core_new_subnav_item( $args, $component = null ) {
     401        // Backward compatibility for plugins using `bp_core_new_subnav_item()` without `$component`
     402        // to add group subnav items.
     403        if ( null === $component && bp_is_active( 'groups' ) && bp_is_group() && isset( $args['parent_slug'] ) ) {
     404                /*
     405                 * Assume that this item is intended to belong to the current group if:
     406                 * a) the 'parent_slug' is the same as the slug of the current group, or
     407                 * b) the 'parent_slug' starts with the slug of the current group, and the members nav doesn't have
     408                 *    a primary item with that slug
     409                 */
     410                $group_slug = bp_get_current_group_slug();
     411                if (
     412                        $group_slug === $args['parent_slug'] ||
     413                        ( 0 === strpos( $args['parent_slug'], $group_slug ) && ! buddypress()->members->nav->get_primary( array( 'slug' => $args['parent_slug'] ), false ) )
     414                ) {
     415                        $component = 'groups';
     416                }
     417        }
    409418
    410         // First, add the subnav item link to the bp_options_nav array.
    411         $created = bp_core_create_subnav_link( $args );
     419        if ( ! $component ) {
     420                $component = 'members';
     421        }
     422
     423        if ( ! bp_is_active( $component ) ) {
     424                return;
     425        }
     426
     427        // First, register the subnav item in the nav.
     428        $subnav_item = bp_core_create_subnav_link( $args, $component );
    412429
    413         // To mimic the existing behavior, if bp_core_create_subnav_link()
    414         // returns false, we make an early exit and don't attempt to register
    415         // the screen function.
    416         if ( false === $created ) {
     430        /*
     431         * To mimic legacy behavior, if bp_core_create_subnav_link() returns false, we make an
     432         * early exit and don't attempt to register the screen function.
     433         */
     434        if ( false === $subnav_item ) {
    417435                return false;
    418436        }
    419437
    420438        // Then, hook the screen function for the added subnav item.
    421         $hooked = bp_core_register_subnav_screen_function( $args );
     439        $hooked = bp_core_register_subnav_screen_function( $subnav_item, $component );
    422440        if ( false === $hooked ) {
    423441                return false;
    424442        }
    function bp_core_new_subnav_item( $args = '' ) { 
    428446 * Add a subnav link to the BuddyPress navigation.
    429447 *
    430448 * @since 2.4.0
     449 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
    431450 *
    432451 * @param array|string $args {
    433452 *     Array describing the new subnav item.
    function bp_core_new_subnav_item( $args = '' ) { 
    455474 *                                          the group's "Edit" Admin Bar menu for group admins.
    456475 *                                          Default: false.
    457476 * }
    458  * @return bool|null Returns false on failure.
     477 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     478 * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
    459479 */
    460 function bp_core_create_subnav_link( $args = '' ) {
     480function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
    461481        $bp = buddypress();
    462482
    463483        $r = wp_parse_args( $args, array(
    function bp_core_create_subnav_link( $args = '' ) { 
    483503        if ( empty( $r['link'] ) ) {
    484504                $r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] );
    485505
     506                $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     507
    486508                // If this sub item is the default for its parent, skip the slug.
    487                 if ( ! empty( $bp->bp_nav[$r['parent_slug']]['default_subnav_slug'] ) && $r['slug'] == $bp->bp_nav[$r['parent_slug']]['default_subnav_slug'] ) {
    488                         $r['link'] = trailingslashit( $r['parent_url'] );
     509                if ( $parent_nav ) {
     510                        $parent_nav_item = reset( $parent_nav );
     511                        if ( ! empty( $parent_nav_item->default_subnav_slug ) && $r['slug'] === $parent_nav_item->default_subnav_slug ) {
     512                                $r['link'] = trailingslashit( $r['parent_url'] );
     513                        }
    489514                }
    490515        }
    491516
    function bp_core_create_subnav_link( $args = '' ) { 
    502527                'name'              => $r['name'],
    503528                'link'              => $r['link'],
    504529                'slug'              => $r['slug'],
     530                'parent_slug'       => $r['parent_slug'],
    505531                'css_id'            => $r['item_css_id'],
    506532                'position'          => $r['position'],
    507533                'user_has_access'   => $r['user_has_access'],
    function bp_core_create_subnav_link( $args = '' ) { 
    510536                'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
    511537        );
    512538
    513         $bp->bp_options_nav[$r['parent_slug']][$r['slug']] = $subnav_item;
     539        return buddypress()->{$component}->nav->add_nav( $subnav_item );
    514540}
    515541
    516542/**
    517543 * Register a screen function, whether or not a related subnav link exists.
    518544 *
    519545 * @since 2.4.0
     546 * @since 2.6.0 Introduced the `$component` parameter.
    520547 *
    521548 * @param array|string $args {
    522549 *     Array describing the new subnav item.
    function bp_core_create_subnav_link( $args = '' ) { 
    541568 *                                       the group's "Edit" Admin Bar menu for group admins.
    542569 *                                       Default: false.
    543570 * }
     571 * @param string $component The component the navigation is attached to. Defaults to 'members'.
    544572 * @return bool|null Returns false on failure.
    545573 */
    546 function bp_core_register_subnav_screen_function( $args = '' ) {
     574function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
    547575        $bp = buddypress();
    548576
    549577        $r = wp_parse_args( $args, array(
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    555583                'screen_function'   => false, // The name of the function to run when clicked.
    556584        ) );
    557585
    558         /**
     586        /*
    559587         * Hook the screen function for the added subnav item. But this only needs to
    560588         * be done if this subnav item is the current view, and the user has access to the
    561589         * subnav item. We figure out whether we're currently viewing this subnav by
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    568596         *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
    569597         *       and this subnav item is the default for the parent item (which we check by
    570598         *       comparing this subnav item's screen function with the screen function of the
    571          *       parent nav item in $bp->bp_nav). This condition only arises when viewing a
    572          *       user, since groups should always have an action set.
     599         *       parent nav item in the component's primary nav). This condition only arises
     600         *       when viewing a user, since groups should always have an action set.
    573601         */
    574602
    575603        // If we *don't* meet condition (1), return.
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    577605                return;
    578606        }
    579607
     608        $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     609
    580610        // If we *do* meet condition (2), then the added subnav item is currently being requested.
    581         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'] ) ) ) {
     611        if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ! empty( $parent_nav->screen_function ) && $r['screen_function'] == $parent_nav->screen_function ) ) {
    582612
    583613                // If this is for site admins only and the user is not one, don't create the subnav item.
    584614                if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
    585615                        return false;
    586616                }
    587617
    588                 $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r );
     618                $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r, $component );
    589619
    590620                // If redirect args have been returned, perform the redirect now.
    591621                if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    598628 * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary.
    599629 *
    600630 * @since 2.1.0
     631 * @since 2.6.0 Introduced the `$component` parameter.
    601632 *
    602  * @param array $subnav_item The subnav array added to bp_options_nav in `bp_core_new_subnav_item()`.
     633 * @param array  $subnav_item The subnav array added to the secondary navigation of
     634 *                            the component in bp_core_new_subnav_item().
     635 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    603636 * @return array
    604637 */
    605 function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) {
     638function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component = 'members' ) {
    606639        $retval = array(
    607640                'status' => '',
    608641        );
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    645678                        // redirect URL.
    646679                        } elseif ( bp_is_user() ) {
    647680
     681                                $parent_nav_default = $bp->{$component}->nav->get_primary( array( 'slug' => $bp->default_component ), false );
     682                                if ( $parent_nav_default ) {
     683                                        $parent_nav_default_item = reset( $parent_nav_default );
     684                                }
     685
    648686                                // Redirect to the displayed user's default
    649687                                // component, as long as that component is
    650688                                // publicly accessible.
    651                                 if ( bp_is_my_profile() || ! empty( $bp->bp_nav[ $bp->default_component ]['show_for_displayed_user'] ) ) {
     689                                if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
    652690                                        $message     = __( 'You do not have access to this page.', 'buddypress' );
    653691                                        $redirect_to = bp_displayed_user_domain();
    654692
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    691729}
    692730
    693731/**
    694  * Sort all subnavigation arrays.
     732 * Check whether a given nav item has subnav items.
    695733 *
    696  * @since 1.1.0
     734 * @since 1.5.0
     735 * @since 2.6.0 Introduced the `$component` parameter.
    697736 *
    698  * @return bool|null Returns false on failure.
     737 * @param string $nav_item  The slug of the top-level nav item whose subnav items you're checking.
     738 *                          Default: the current component slug.
     739 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     740 * @return bool $has_subnav True if the nav item is found and has subnav items; false otherwise.
    699741 */
    700 function bp_core_sort_subnav_items() {
     742function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) {
    701743        $bp = buddypress();
    702744
    703         if ( empty( $bp->bp_options_nav ) || !is_array( $bp->bp_options_nav ) )
     745        if ( ! isset( $bp->{$component}->nav ) ) {
    704746                return false;
     747        }
    705748
    706         foreach ( (array) $bp->bp_options_nav as $parent_slug => $subnav_items ) {
    707                 if ( !is_array( $subnav_items ) )
    708                         continue;
    709 
    710                 foreach ( (array) $subnav_items as $subnav_item ) {
    711                         if ( empty( $temp[$subnav_item['position']]) )
    712                                 $temp[$subnav_item['position']] = $subnav_item;
    713                         else {
    714                                 // Increase numbers here to fit new items in.
    715                                 do {
    716                                         $subnav_item['position']++;
    717                                 } while ( !empty( $temp[$subnav_item['position']] ) );
     749        if ( ! $nav_item ) {
     750                $nav_item = bp_current_component();
    718751
    719                                 $temp[$subnav_item['position']] = $subnav_item;
    720                         }
     752                if ( bp_is_group() ) {
     753                        $nav_item = bp_current_item();
    721754                }
    722                 ksort( $temp );
    723                 $bp->bp_options_nav[$parent_slug] = &$temp;
    724                 unset( $temp );
    725755        }
    726 }
    727 add_action( 'wp_head',    'bp_core_sort_subnav_items' );
    728 add_action( 'admin_head', 'bp_core_sort_subnav_items' );
    729 
    730 /**
    731  * Check whether a given nav item has subnav items.
    732  *
    733  * @since 1.5.0
    734  *
    735  * @param string $nav_item The slug of the top-level nav item whose subnav items you're checking.
    736  *                         Default: the current component slug.
    737  * @return bool $has_subnav True if the nav item is found and has subnav items; false otherwise.
    738  */
    739 function bp_nav_item_has_subnav( $nav_item = '' ) {
    740         $bp = buddypress();
    741 
    742         if ( !$nav_item )
    743                 $nav_item = bp_current_component();
    744756
    745         $has_subnav = isset( $bp->bp_options_nav[$nav_item] ) && count( $bp->bp_options_nav[$nav_item] ) > 0;
     757        $has_subnav = (bool) $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $nav_item ), false );
    746758
    747759        /**
    748760         * Filters whether or not a given nav item has subnav items.
    function bp_nav_item_has_subnav( $nav_item = '' ) { 
    756768}
    757769
    758770/**
    759  * Remove a nav item from the navigation array.
     771 * Deletes an item from the primary navigation of the specified component.
    760772 *
    761  * @since 1.0.0
     773 * @since 2.6.0
    762774 *
    763  * @param int $parent_id The slug of the parent navigation item.
    764  * @return bool Returns false on failure, ie if the nav item can't be found.
     775 * @param string $slug      The slug of the primary navigation item.
     776 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     777 * @return bool Returns false on failure, True on success.
    765778 */
    766 function bp_core_remove_nav_item( $parent_id ) {
     779function bp_core_delete_nav_item( $slug, $component = 'members' ) {
    767780        $bp = buddypress();
    768781
    769         // Unset subnav items for this nav item.
    770         if ( isset( $bp->bp_options_nav[$parent_id] ) && is_array( $bp->bp_options_nav[$parent_id] ) ) {
    771                 foreach( (array) $bp->bp_options_nav[$parent_id] as $subnav_item ) {
    772                         bp_core_remove_subnav_item( $parent_id, $subnav_item['slug'] );
    773                 }
     782        if ( ! isset( $bp->{$component}->nav ) ) {
     783                return false;
    774784        }
    775785
    776         if ( empty( $bp->bp_nav[ $parent_id ] ) )
     786        $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
     787
     788        if ( ! is_array( $screen_functions ) ) {
    777789                return false;
     790        }
    778791
    779         if ( $function = $bp->bp_nav[$parent_id]['screen_function'] ) {
     792        foreach ( $screen_functions as $screen_function ) {
    780793                // Remove our screen hook if screen function is callable.
    781                 if ( is_callable( $function ) ) {
    782                         remove_action( 'bp_screens', $function, 3 );
     794                if ( is_callable( $screen_function ) ) {
     795                        remove_action( 'bp_screens', $screen_function, 3 );
    783796                }
    784797        }
    785798
    786         unset( $bp->bp_nav[$parent_id] );
     799        return true;
    787800}
    788801
    789802/**
    790  * Remove a subnav item from the navigation array.
     803 * Deletes an item from the secondary navigation of the specified component.
    791804 *
    792  * @since 1.0.0
     805 * @since 2.6.0
    793806 *
    794  * @param string $parent_id The slug of the parent navigation item.
    795  * @param string $slug      The slug of the subnav item to be removed.
     807 * @param string $slug        The slug of the secondary item to be removed.
     808 * @param string $parent_slug The slug of the primary navigation item.
     809 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
     810 * @return bool Returns false on failure, True on success.
    796811 */
    797 function bp_core_remove_subnav_item( $parent_id, $slug ) {
     812function bp_core_delete_subnav_item( $slug, $parent_slug, $component = 'members' ) {
    798813        $bp = buddypress();
    799814
    800         $screen_function = isset( $bp->bp_options_nav[$parent_id][$slug]['screen_function'] )
    801                 ? $bp->bp_options_nav[$parent_id][$slug]['screen_function']
    802                 : false;
     815        if ( ! isset( $bp->{$component}->nav ) ) {
     816                return false;
     817        }
    803818
    804         if ( ! empty( $screen_function ) ) {
    805                 // Remove our screen hook if screen function is callable.
    806                 if ( is_callable( $screen_function ) ) {
    807                         remove_action( 'bp_screens', $screen_function, 3 );
    808                 }
     819        $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
     820
     821        if ( ! is_array( $screen_functions ) ) {
     822                return false;
    809823        }
    810824
    811         unset( $bp->bp_options_nav[$parent_id][$slug] );
     825        $screen_function = reset( $screen_functions );
     826
     827        // Remove our screen hook if screen function is callable.
     828        if ( is_callable( $screen_function ) ) {
     829                remove_action( 'bp_screens', $screen_function, 3 );
     830        }
    812831
    813         if ( isset( $bp->bp_options_nav[$parent_id] ) && !count( $bp->bp_options_nav[$parent_id] ) )
    814                 unset($bp->bp_options_nav[$parent_id]);
     832        return true;
    815833}
    816834
    817835/**
    818836 * Clear all subnav items from a specific nav item.
    819837 *
    820838 * @since 1.0.0
     839 * @since 2.6.0 Introduced the `$component` parameter.
    821840 *
    822841 * @param string $parent_slug The slug of the parent navigation item.
     842 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    823843 */
    824 function bp_core_reset_subnav_items( $parent_slug ) {
     844function bp_core_reset_subnav_items( $parent_slug, $component = 'members' ) {
    825845        $bp = buddypress();
    826846
    827         unset( $bp->bp_options_nav[$parent_slug] );
     847        if ( ! isset( $bp->{$component}->nav ) ) {
     848                return;
     849        }
     850
     851        $subnav_items = $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $parent_slug ), false );
     852
     853        if ( ! $subnav_items ) {
     854                return;
     855        }
     856
     857        foreach( $subnav_items as $subnav_item ) {
     858                $bp->{$component}->nav->delete_nav( $subnav_item->slug, $parent_slug );
     859        }
    828860}
    829861
    830862
  • src/bp-core/bp-core-classes.php

    diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php
    index bebf4ed..9d2d377 100644
    require dirname( __FILE__ ) . '/classes/class-bp-email-recipient.php'; 
    3030require dirname( __FILE__ ) . '/classes/class-bp-email.php';
    3131require dirname( __FILE__ ) . '/classes/class-bp-email-delivery.php';
    3232require dirname( __FILE__ ) . '/classes/class-bp-phpmailer.php';
     33require dirname( __FILE__ ) . '/classes/class-bp-core-nav.php';
     34require dirname( __FILE__ ) . '/classes/class-bp-core-nav-item.php';
     35
     36if ( buddypress()->do_nav_backcompat ) {
     37        require dirname( __FILE__ ) . '/classes/class-bp-core-bp-nav-backcompat.php';
     38        require dirname( __FILE__ ) . '/classes/class-bp-core-bp-options-nav-backcompat.php';
     39}
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 702d0dd..a489fd4 100644
    function bp_nav_menu_get_loggedin_pages() { 
    24432443                return buddypress()->wp_nav_menu_items->loggedin;
    24442444        }
    24452445
    2446         // Pull up a list of items registered in BP's top-level nav array.
    2447         $bp_menu_items = buddypress()->bp_nav;
    2448 
    2449         // Alphabetize.
    2450         $bp_menu_items = bp_alpha_sort_by_key( $bp_menu_items, 'name' );
     2446        // Pull up a list of items registered in BP's primary nav for the member.
     2447        $bp_menu_items = buddypress()->members->nav->get_primary();
    24512448
    24522449        // Some BP nav menu items will not be represented in bp_nav, because
    24532450        // they are not real BP components. We add them manually here.
    function bp_nav_menu_get_loggedin_pages() { 
    24782475                        'post_type'      => 'page',
    24792476                        'post_status'    => 'publish',
    24802477                        'comment_status' => 'closed',
    2481                         'guid'           => $bp_item['link']
     2478                        'guid'           => $bp_item['link'],
    24822479                );
    24832480        }
    24842481
    function bp_nav_menu_get_loggedout_pages() { 
    25752572 * @since 1.9.0
    25762573 *
    25772574 * @param string $slug The slug of the nav item: login, register, or one of the
    2578  *                     slugs from buddypress()->bp_nav.
     2575 *                     slugs from the members navigation.
    25792576 * @return string $nav_item_url The URL generated for the current user.
    25802577 */
    25812578function bp_nav_menu_get_item_url( $slug ) {
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index 1f2c5e9..abfb275 100644
    defined( 'ABSPATH' ) || exit; 
    1313/**
    1414 * Output the "options nav", the secondary-level single item navigation menu.
    1515 *
    16  * Uses the $bp->bp_options_nav global to render out the sub navigation for the
     16 * Uses the component's nav global to render out the sub navigation for the
    1717 * current component. Each component adds to its sub navigation array within
    1818 * its own setup_nav() function.
    1919 *
    function bp_get_options_nav( $parent_slug = '' ) { 
    4040        $component_index = !empty( $bp->displayed_user ) ? bp_current_component() : bp_get_root_slug( bp_current_component() );
    4141        $selected_item   = bp_current_action();
    4242
     43        // Default to the Members nav.
    4344        if ( ! bp_is_single_item() ) {
    44                 if ( !isset( $bp->bp_options_nav[$component_index] ) || count( $bp->bp_options_nav[$component_index] ) < 1 ) {
     45                // Set the parent slug, if not provided.
     46                if ( empty( $parent_slug ) ) {
     47                        $parent_slug = $component_index;
     48                }
     49
     50                $secondary_nav_items = $bp->members->nav->get_secondary( array( 'parent_slug' => $parent_slug ) );
     51
     52                if ( ! $secondary_nav_items ) {
    4553                        return false;
    46                 } else {
    47                         $the_index = $component_index;
    4854                }
     55
     56        // For a single item, try to use the component's nav.
    4957        } else {
    5058                $current_item = bp_current_item();
     59                $single_item_component = bp_current_component();
    5160
     61                // Adjust the selected nav item for the current single item if needed.
    5262                if ( ! empty( $parent_slug ) ) {
    5363                        $current_item  = $parent_slug;
    5464                        $selected_item = bp_action_variable( 0 );
    5565                }
    5666
    57                 if ( !isset( $bp->bp_options_nav[$current_item] ) || count( $bp->bp_options_nav[$current_item] ) < 1 ) {
    58                         return false;
     67                // If the nav is not defined by the parent component, look in the Members nav.
     68                if ( ! isset( $bp->{$single_item_component}->nav ) ) {
     69                        $secondary_nav_items = $bp->members->nav->get_secondary( array( 'parent_slug' => $current_item ) );
    5970                } else {
    60                         $the_index = $current_item;
     71                        $secondary_nav_items = $bp->{$single_item_component}->nav->get_secondary( array( 'parent_slug' => $current_item ) );
     72                }
     73
     74                if ( ! $secondary_nav_items ) {
     75                        return false;
    6176                }
    6277        }
    6378
    6479        // Loop through each navigation item.
    65         foreach ( (array) $bp->bp_options_nav[$the_index] as $subnav_item ) {
    66                 if ( empty( $subnav_item['user_has_access'] ) ) {
     80        foreach ( $secondary_nav_items as $subnav_item ) {
     81                if ( empty( $subnav_item->user_has_access ) ) {
    6782                        continue;
    6883                }
    6984
    7085                // If the current action or an action variable matches the nav item id, then add a highlight CSS class.
    71                 if ( $subnav_item['slug'] == $selected_item ) {
     86                if ( $subnav_item->slug === $selected_item ) {
    7287                        $selected = ' class="current selected"';
    7388                } else {
    7489                        $selected = '';
    function bp_get_options_nav( $parent_slug = '' ) { 
    88103                 * @param array  $subnav_item   Submenu array item being displayed.
    89104                 * @param string $selected_item Current action.
    90105                 */
    91                 echo apply_filters( 'bp_get_options_nav_' . $subnav_item['css_id'], '<li id="' . esc_attr( $subnav_item['css_id'] . '-' . $list_type . '-li' ) . '" ' . $selected . '><a id="' . esc_attr( $subnav_item['css_id'] ) . '" href="' . esc_url( $subnav_item['link'] ) . '">' . $subnav_item['name'] . '</a></li>', $subnav_item, $selected_item );
     106                echo apply_filters( 'bp_get_options_nav_' . $subnav_item->css_id, '<li id="' . esc_attr( $subnav_item->css_id . '-' . $list_type . '-li' ) . '" ' . $selected . '><a id="' . esc_attr( $subnav_item->css_id ) . '" href="' . esc_url( $subnav_item->link ) . '">' . $subnav_item->name . '</a></li>', $subnav_item, $selected_item );
    92107        }
    93108}
    94109
    function bp_get_title_parts( $seplocation = 'right' ) { 
    30103025                // Set empty subnav name.
    30113026                $component_subnav_name = '';
    30123027
     3028                if ( ! empty( $bp->members->nav ) ) {
     3029                        $primary_nav_item = $bp->members->nav->get_primary( array( 'slug' => $component_id ), false );
     3030                        $primary_nav_item = reset( $primary_nav_item );
     3031                }
     3032
    30133033                // Use the component nav name.
    3014                 if ( ! empty( $bp->bp_nav[$component_id] ) ) {
    3015                         $component_name = _bp_strip_spans_from_title( $bp->bp_nav[ $component_id ]['name'] );
     3034                if ( ! empty( $primary_nav_item->name ) ) {
     3035                        $component_name = _bp_strip_spans_from_title( $primary_nav_item->name );
    30163036
    30173037                // Fall back on the component ID.
    30183038                } elseif ( ! empty( $bp->{$component_id}->id ) ) {
    30193039                        $component_name = ucwords( $bp->{$component_id}->id );
    30203040                }
    30213041
    3022                 // Append action name if we're on a member component sub-page.
    3023                 if ( ! empty( $bp->bp_options_nav[ $component_id ] ) && ! empty( $bp->canonical_stack['action'] ) ) {
    3024                         $component_subnav_name = wp_filter_object_list( $bp->bp_options_nav[ $component_id ], array( 'slug' => bp_current_action() ), 'and', 'name' );
     3042                if ( ! empty( $bp->members->nav ) ) {
     3043                        $secondary_nav_item = $bp->members->nav->get_secondary( array(
     3044                                'parent_slug' => $component_id,
     3045                                'slug'        => bp_current_action()
     3046                        ), false );
    30253047
    3026                         if ( ! empty( $component_subnav_name ) ) {
    3027                                 $component_subnav_name = array_shift( $component_subnav_name );
     3048                        if ( $secondary_nav_item ) {
     3049                                $secondary_nav_item = reset( $secondary_nav_item );
    30283050                        }
    30293051                }
    30303052
     3053                // Append action name if we're on a member component sub-page.
     3054                if ( ! empty( $secondary_nav_item->name ) && ! empty( $bp->canonical_stack['action'] ) ) {
     3055                        $component_subnav_name = $secondary_nav_item->name;
     3056                }
     3057
    30313058                // If on the user profile's landing page, just use the fullname.
    30323059                if ( bp_is_current_component( $bp->default_component ) && ( bp_get_requested_url() === bp_displayed_user_domain() ) ) {
    30333060                        $bp_title_parts[] = $displayed_user_name;
    function bp_get_title_parts( $seplocation = 'right' ) { 
    30453072                        }
    30463073                }
    30473074
    3048         // A single group.
    3049         } elseif ( bp_is_active( 'groups' ) && ! empty( $bp->groups->current_group ) && ! empty( $bp->bp_options_nav[ $bp->groups->current_group->slug ] ) ) {
    3050                 $subnav      = isset( $bp->bp_options_nav[ $bp->groups->current_group->slug ][ bp_current_action() ]['name'] ) ? $bp->bp_options_nav[ $bp->groups->current_group->slug ][ bp_current_action() ]['name'] : '';
    3051                 $bp_title_parts = array( $bp->bp_options_title, $subnav );
    3052 
    3053         // A single item from a component other than groups.
     3075        // A single item from a component other than Members.
    30543076        } elseif ( bp_is_single_item() ) {
    3055                 $bp_title_parts = array( $bp->bp_options_title, $bp->bp_options_nav[ bp_current_item() ][ bp_current_action() ]['name'] );
     3077                $component_id = bp_current_component();
     3078
     3079                if ( ! empty( $bp->{$component_id}->nav ) ) {
     3080                        $secondary_nav_item = $bp->{$component_id}->nav->get_secondary( array(
     3081                                'parent_slug' => bp_current_item(),
     3082                                'slug'        => bp_current_action()
     3083                        ), false );
     3084
     3085                        if ( $secondary_nav_item ) {
     3086                                $secondary_nav_item = reset( $secondary_nav_item );
     3087                        }
     3088                }
     3089
     3090                $single_item_subnav = '';
     3091
     3092                if ( ! empty( $secondary_nav_item->name ) ) {
     3093                        $single_item_subnav = $secondary_nav_item->name;
     3094                }
     3095
     3096                $bp_title_parts = array( $bp->bp_options_title, $single_item_subnav );
    30563097
    30573098        // An index or directory.
    30583099        } elseif ( bp_is_directory() ) {
    function _bp_nav_menu_sort( $a, $b ) { 
    34283469 * Get the items registered in the primary and secondary BuddyPress navigation menus.
    34293470 *
    34303471 * @since 1.7.0
     3472 * @since 2.6.0 Introduced the `$component` parameter.
    34313473 *
     3474 * @param string $component Optional. Component whose nav items are being fetched.
    34323475 * @return array A multidimensional array of all navigation items.
    34333476 */
    3434 function bp_get_nav_menu_items() {
    3435         $menus = $selected_menus = array();
    3436 
    3437         // Get the second level menus.
    3438         foreach ( (array) buddypress()->bp_options_nav as $parent_menu => $sub_menus ) {
    3439 
    3440                 // The root menu's ID is "xprofile", but the Profile submenus are using "profile". See BP_Core::setup_nav().
    3441                 if ( 'profile' === $parent_menu ) {
    3442                         $parent_menu = 'xprofile';
    3443                 }
    3444 
    3445                 // Sort the items in this menu's navigation by their position property.
    3446                 $second_level_menus = (array) $sub_menus;
    3447                 usort( $second_level_menus, '_bp_nav_menu_sort' );
    3448 
    3449                 // Iterate through the second level menus.
    3450                 foreach( $second_level_menus as $sub_nav ) {
    3451 
    3452                         // Skip items we don't have access to.
    3453                         if ( empty( $sub_nav['user_has_access'] ) ) {
    3454                                 continue;
    3455                         }
    3456 
    3457                         // Add this menu.
    3458                         $menu         = new stdClass;
    3459                         $menu->class  = array( 'menu-child' );
    3460                         $menu->css_id = $sub_nav['css_id'];
    3461                         $menu->link   = $sub_nav['link'];
    3462                         $menu->name   = $sub_nav['name'];
    3463                         $menu->parent = $parent_menu;  // Associate this sub nav with a top-level menu.
    3464 
    3465                         // If we're viewing this item's screen, record that we need to mark its parent menu to be selected.
    3466                         if ( $sub_nav['slug'] == bp_current_action() ) {
    3467                                 $menu->class[]    = 'current-menu-item';
    3468                                 $selected_menus[] = $parent_menu;
    3469                         }
     3477function bp_get_nav_menu_items( $component = 'members' ) {
     3478        $bp    = buddypress();
     3479        $menus = array();
    34703480
    3471                         $menus[] = $menu;
    3472                 }
     3481        if ( ! isset( $bp->{$component}->nav ) ) {
     3482                return $menus;
    34733483        }
    34743484
    3475         // Get the top-level menu parts (Friends, Groups, etc) and sort by their position property.
    3476         $top_level_menus = (array) buddypress()->bp_nav;
    3477         usort( $top_level_menus, '_bp_nav_menu_sort' );
    3478 
    3479         // Iterate through the top-level menus.
    3480         foreach ( $top_level_menus as $nav ) {
    3481 
    3482                 // Skip items marked as user-specific if you're not on your own profile.
    3483                 if ( empty( $nav['show_for_displayed_user'] ) && ! bp_core_can_edit_settings()  ) {
    3484                         continue;
    3485                 }
    3486 
     3485        // Get the item nav and build the menus.
     3486        foreach ( $bp->{$component}->nav->get_item_nav() as $nav_menu ) {
    34873487                // Get the correct menu link. See https://buddypress.trac.wordpress.org/ticket/4624.
    3488                 $link = bp_loggedin_user_domain() ? str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $nav['link'] ) : trailingslashit( bp_displayed_user_domain() . $nav['link'] );
     3488                $link = bp_loggedin_user_domain() ? str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $nav_menu->link ) : trailingslashit( bp_displayed_user_domain() . $nav_menu->link );
    34893489
    34903490                // Add this menu.
    34913491                $menu         = new stdClass;
    34923492                $menu->class  = array( 'menu-parent' );
    3493                 $menu->css_id = $nav['css_id'];
    3494                 $menu->link   = $link;
    3495                 $menu->name   = $nav['name'];
     3493                $menu->css_id = $nav_menu->css_id;
     3494                $menu->link   = $nav_menu->link;
     3495                $menu->name   = $nav_menu->name;
    34963496                $menu->parent = 0;
    34973497
    3498                 // Check if we need to mark this menu as selected.
    3499                 if ( in_array( $nav['css_id'], $selected_menus ) ) {
    3500                         $menu->class[] = 'current-menu-parent';
     3498                if ( ! empty( $nav_menu->children ) ) {
     3499                        $submenus = array();
     3500
     3501                        foreach( $nav_menu->children as $sub_menu ) {
     3502                                $submenu = new stdClass;
     3503                                $submenu->class  = array( 'menu-child' );
     3504                                $submenu->css_id = $sub_menu->css_id;
     3505                                $submenu->link   = $sub_menu->link;
     3506                                $submenu->name   = $sub_menu->name;
     3507                                $submenu->parent = $nav_menu->slug;
     3508
     3509                                // If we're viewing this item's screen, record that we need to mark its parent menu to be selected.
     3510                                if ( $sub_menu->slug == bp_current_action() ) {
     3511                                        $menu->class[]    = 'current-menu-parent';
     3512                                        $submenu->class[] = 'current-menu-item';
     3513                                }
     3514
     3515                                $submenus[] = $submenu;
     3516                        }
    35013517                }
    35023518
    35033519                $menus[] = $menu;
     3520
     3521                if ( ! empty( $submenus ) ) {
     3522                        $menus = array_merge( $menus, $submenus );
     3523                }
    35043524        }
    35053525
    35063526        /**
  • src/bp-core/classes/class-bp-component.php

    diff --git src/bp-core/classes/class-bp-component.php src/bp-core/classes/class-bp-component.php
    index 8a53680..d9096dd 100644
    class BP_Component { 
    489489
    490490                // No sub nav items without a main nav item.
    491491                if ( !empty( $main_nav ) ) {
    492                         bp_core_new_nav_item( $main_nav );
     492                        bp_core_new_nav_item( $main_nav, 'members' );
    493493
    494494                        // Sub nav items are not required.
    495495                        if ( !empty( $sub_nav ) ) {
    496496                                foreach( (array) $sub_nav as $nav ) {
    497                                         bp_core_new_subnav_item( $nav );
     497                                        bp_core_new_subnav_item( $nav, 'members' );
    498498                                }
    499499                        }
    500500                }
  • new file src/bp-core/classes/class-bp-core-bp-nav-backcompat.php

    diff --git src/bp-core/classes/class-bp-core-bp-nav-backcompat.php src/bp-core/classes/class-bp-core-bp-nav-backcompat.php
    new file mode 100644
    index 0000000..cf39fe5
    - +  
     1<?php
     2/**
     3 * Backward compatibility for the $bp->bp_nav global.
     4 *
     5 * @since 2.6.0
     6 */
     7
     8// Exit if accessed directly.
     9defined( 'ABSPATH' ) || exit;
     10
     11/**
     12 * bp_nav backward compatibility class.
     13 *
     14 * This class is used to provide backward compatibility for extensions that access and modify
     15 * the $bp->bp_nav global.
     16 *
     17 * @since 2.6.0
     18 */
     19class BP_Core_BP_Nav_BackCompat implements ArrayAccess {
     20        /**
     21         * Nav items.
     22         *
     23         * @since 2.6.0
     24         * @access public
     25         * @var array
     26         */
     27        public $backcompat_nav = array();
     28
     29        /**
     30         * Component to which nav items belong.
     31         *
     32         * @since 2.6.0
     33         * @access public
     34         * @var array
     35         */
     36        public $component;
     37
     38        /**
     39         * Constructor.
     40         *
     41         * @since 2.6.0
     42         *
     43         * @param array $backcompat_nav Optional. Array of nav items.
     44         */
     45        public function __construct( $backcompat_nav = array() ) {
     46                foreach ( $backcompat_nav as $key => $value ) {
     47                        if ( is_array( $value ) ) {
     48                                $this->backcompat_nav[ $key ] = new self( $value );
     49                        } else {
     50                                $this->backcompat_nav[ $key ] = $value;
     51                        }
     52                }
     53        }
     54
     55        /**
     56         * Assign a value to the nav array at the specified offset.
     57         *
     58         * @since 2.6.0
     59         *
     60         * @param mixed $offset Array offset.
     61         * @param array $value  Nav item.
     62         */
     63        public function offsetSet( $offset, $value ) {
     64                _doing_it_wrong(
     65                        'bp_nav',
     66                        __( 'The bp_nav and bp_options_nav globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     67                        '2.6.0'
     68                );
     69
     70                $bp = buddypress();
     71
     72                if ( is_array( $value ) ) {
     73                        $value = new self( $value );
     74                }
     75
     76                if ( $offset !== null ) {
     77                        // Temporarily set the backcompat_nav.
     78                        $this->backcompat_nav[ $offset ] = $value;
     79
     80                        $args = $this->to_array();
     81                        if ( isset( $args['parent_slug'] ) ) {
     82                                $this->get_component_nav( $args['parent_slug'] )->edit_nav( $args, $args['slug'], $args['parent_slug'] );
     83                        } elseif ( isset( $args['slug'] ) ) {
     84                                $bp->members->nav->edit_nav( $args, $args['slug'] );
     85                        }
     86                }
     87        }
     88
     89        /**
     90         * Get a value of the nav array at the specified offset.
     91         *
     92         * @since 2.6.0
     93         *
     94         * @param mixed $offset Array offset.
     95         * @return BP_Core_BP_Nav_BackCompat
     96         */
     97        public function offsetGet( $offset ) {
     98                _doing_it_wrong(
     99                        'bp_nav',
     100                        __( 'The bp_nav and bp_options_nav globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     101                        '2.6.0'
     102                );
     103
     104                if ( ! isset( $this->backcompat_nav[ $offset ] ) ) {
     105                        $nav = $this->get_nav( $offset );
     106                        if ( $nav && isset( $nav[ $offset ] ) ) {
     107                                $this->backcompat_nav[ $offset ] = new self( $nav[ $offset ] );
     108                        }
     109                }
     110
     111                return $this->backcompat_nav[ $offset ];
     112        }
     113
     114        /**
     115         * Check whether nav array has a value at the specified offset.
     116         *
     117         * @since 2.6.0
     118         *
     119         * @param mixed $offset Array offset.
     120         * @return bool
     121         */
     122        public function offsetExists( $offset ) {
     123                _doing_it_wrong(
     124                        'bp_nav',
     125                        __( 'The bp_nav and bp_options_nav globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     126                        '2.6.0'
     127                );
     128
     129                if ( isset( $this->backcompat_nav[ $offset ] ) ) {
     130                        return true;
     131                }
     132
     133                $nav = $this->get_nav( $offset );
     134                if ( $nav && isset( $nav[ $offset ] ) ) {
     135                        return true;
     136                }
     137
     138                return false;
     139        }
     140
     141        /**
     142         * Unset a nav array value at the specified offset.
     143         *
     144         * @since 2.6.0
     145         *
     146         * @param mixed $offset Array offset.
     147         */
     148        public function offsetUnset( $offset ) {
     149                _doing_it_wrong(
     150                        'bp_nav',
     151                        __( 'The bp_nav and bp_options_nav globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     152                        '2.6.0'
     153                );
     154
     155                // For top-level nav items, the backcompat nav hasn't yet been initialized.
     156                if ( ! isset( $this->backcompat_nav[ $offset ] ) ) {
     157                        buddypress()->members->nav->delete_nav( $offset );
     158                        unset( $this->backcompat_nav[ $offset ] );
     159                }
     160        }
     161
     162        /**
     163         * Set the component to which the nav belongs.
     164         *
     165         * @since 2.6.0
     166         *
     167         * @param string $component
     168         */
     169        public function set_component( $component ) {
     170                $this->component = $component;
     171        }
     172
     173        /**
     174         * Get the component to which the a nav item belongs.
     175         *
     176         * We use the following heuristic to guess, based on an offset, which component the item belongs to:
     177         *   - If this is a group, and the offset is the same as the current group's slug, it's a group nav item.
     178         *   - Otherwise, it's a member nav item.
     179         *
     180         * @since 2.6.0
     181         *
     182         * @param mixed $offset Array offset.
     183         * @return string
     184         */
     185        public function get_component( $offset = '' ) {
     186                if ( ! isset( $this->component ) ) {
     187                        if ( bp_is_active( 'groups' ) && $offset === bp_get_current_group_slug() ) {
     188                                $this->component = 'groups';
     189                        } else {
     190                                $this->component = 'members';
     191                        }
     192                }
     193
     194                return $this->component;
     195        }
     196
     197        /**
     198         * Get the nav object corresponding to the specified offset.
     199         *
     200         * @since 2.6.0
     201         *
     202         * @param mixed $offset Array offset.
     203         * @return bool|array
     204         */
     205        protected function get_nav( $offset ) {
     206                $bp = buddypress();
     207
     208                $component_nav = $this->get_component_nav( $offset );
     209                $primary_nav   = $component_nav->get_primary( array( 'slug' => $offset ), false );
     210
     211                $nav = array();
     212
     213                if ( empty( $primary_nav ) ) {
     214                        return $nav;
     215                }
     216
     217                foreach ( $primary_nav as $item ) {
     218                        $nav[ $item->slug ] = (array) $item;
     219                }
     220
     221                return $nav;
     222        }
     223
     224        /**
     225         * Get the BP_Core_Nav object corresponding to the component, based on a nav item name.
     226         *
     227         * The way bp_nav was previously organized makes it impossible to know for sure which component's nav is
     228         * being referenced by a given nav item name. We guess in the following manner:
     229         *   - If we're looking at a group, and the nav item name (`$offset`) is the same as the slug of the current
     230         *     group, we assume that the proper component nav is 'groups'.
     231         *   - Otherwise, fall back on 'members'.
     232         *
     233         * @since 2.6.0
     234         *
     235         * @param string $offset Nav item name.
     236         * @return BP_Core_Nav
     237         */
     238        protected function get_component_nav( $offset = '' ) {
     239                $component = $this->get_component( $offset );
     240
     241                $bp = buddypress();
     242                if ( ! isset( $bp->{$component}->nav ) ) {
     243                        return false;
     244                }
     245
     246                return $bp->{$component}->nav;
     247        }
     248
     249        /**
     250         * Get the nav data, formatted as a flat array.
     251         *
     252         * @since 2.6.0
     253         *
     254         * @return array
     255         */
     256        protected function to_array() {
     257                return $this->backcompat_nav;
     258        }
     259}
  • new file src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php

    diff --git src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php
    new file mode 100644
    index 0000000..a91eb44
    - +  
     1<?php
     2/**
     3 * Backward compatibility for the $bp->bp_options_nav global.
     4 *
     5 * @since 2.6.0
     6 */
     7
     8// Exit if accessed directly.
     9defined( 'ABSPATH' ) || exit;
     10
     11/**
     12 * bp_options_nav backward compatibility class.
     13 *
     14 * This class is used to provide backward compatibility for extensions that access and modify
     15 * the $bp->bp_options_nav global.
     16 *
     17 * @since 2.6.0
     18 */
     19class BP_Core_BP_Options_Nav_BackCompat extends BP_Core_BP_Nav_BackCompat {
     20        /**
     21         * Parent slug of the current nav item.
     22         *
     23         * @since 2.6.0
     24         * @access protected
     25         * @var string
     26         */
     27        protected $parent_slug = '';
     28
     29        /**
     30         * Get a value of the nav array at the specified offset.
     31         *
     32         * @since 2.6.0
     33         *
     34         * @param mixed $offset Array offset.
     35         * @return BP_Core_BP_Nav_BackCompat
     36         */
     37        public function offsetGet( $offset ) {
     38                _doing_it_wrong(
     39                        'bp_nav',
     40                        __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     41                        '2.6.0'
     42                );
     43
     44                if ( empty( $this->backcompat_nav[ $offset ] ) ) {
     45                        $nav = $this->get_nav( $offset );
     46                        if ( $nav ) {
     47                                $subnavs = $this->get_component_nav( $offset )->get_secondary( array( 'parent_slug' => $offset ) );
     48                                $subnav_keyed = array();
     49                                foreach ( $subnavs as $subnav ) {
     50                                        $subnav_keyed[ $subnav->slug ] = (array) $subnav;
     51                                }
     52
     53                                $subnav_object = new self( $subnav_keyed );
     54                                $subnav_object->set_component( $this->get_component() );
     55                                $subnav_object->set_parent_slug( $offset );
     56
     57                                $this->backcompat_nav[ $offset ] = $subnav_object;
     58                        }
     59                }
     60
     61                return $this->backcompat_nav[ $offset ];
     62        }
     63
     64        /**
     65         * Unset a nav array value at the specified offset.
     66         *
     67         * @since 2.6.0
     68         *
     69         * @param mixed $offset Array offset.
     70         */
     71        public function offsetUnset( $offset ) {
     72                _doing_it_wrong(
     73                        'bp_nav',
     74                        __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     75                        '2.6.0'
     76                );
     77
     78                $this->get_component_nav( $offset )->delete_nav( $offset, $this->get_parent_slug() );
     79
     80                // Clear the cached nav.
     81                unset( $this->backcompat_nav[ $offset ] );
     82        }
     83
     84        /**
     85         * Get the parent slug of the current nav item.
     86         *
     87         * @since 2.6.0
     88         *
     89         * @return string
     90         */
     91        public function get_parent_slug() {
     92                return $this->parent_slug;
     93        }
     94
     95        /**
     96         * Set the parent slug of the current nav item.
     97         *
     98         * @since 2.6.0
     99         */
     100        public function set_parent_slug( $slug ) {
     101                $this->parent_slug = $slug;
     102        }
     103
     104        /**
     105         * Get the nav object corresponding to the specified offset.
     106         *
     107         * @since 2.6.0
     108         *
     109         * @param mixed $offset Array offset.
     110         * @return bool|array
     111         */
     112        public function get_nav( $offset ) {
     113                $nav = parent::get_nav( $offset );
     114
     115                if ( ! $nav ) {
     116                        $component_nav = $this->get_component_nav( $offset );
     117                        $secondary_nav = $component_nav->get_secondary( array( 'slug' => $offset ), false );
     118
     119                        $nav = array();
     120
     121                        if ( empty( $primary_nav ) ) {
     122                                return $nav;
     123                        }
     124
     125                        foreach ( $primary_nav as $item ) {
     126                                $nav[ $item->slug ] = (array) $item;
     127                        }
     128                }
     129
     130                return $nav;
     131        }
     132}
  • new file src/bp-core/classes/class-bp-core-nav-item.php

    diff --git src/bp-core/classes/class-bp-core-nav-item.php src/bp-core/classes/class-bp-core-nav-item.php
    new file mode 100644
    index 0000000..8b901b3
    - +  
     1<?php
     2
     3// Exit if accessed directly.
     4defined( 'ABSPATH' ) || exit;
     5
     6if ( class_exists( 'ArrayObject' ) ) :
     7
     8/**
     9 * Navigation item.
     10 *
     11 * @since 2.6.0
     12 */
     13class BP_Core_Nav_Item extends ArrayObject {
     14        public function __construct( $data ) {
     15                parent::__construct( $data, ArrayObject::ARRAY_AS_PROPS );
     16        }
     17}
     18
     19else :
     20
     21/**
     22 * Navigation item.
     23 *
     24 * @since 2.6.0
     25 */
     26class BP_Core_Nav_Item {
     27        public function __construct( $data ) {
     28                foreach ( $data as $key => $value ) {
     29                        $this->key = $value;
     30                }
     31        }
     32}
     33
     34endif;
  • new file src/bp-core/classes/class-bp-core-nav.php

    diff --git src/bp-core/classes/class-bp-core-nav.php src/bp-core/classes/class-bp-core-nav.php
    new file mode 100644
    index 0000000..a13fec8
    - +  
     1<?php
     2/**
     3 * Core component class.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 * @since  2.6.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * BuddyPress Nav.
     15 *
     16 * This class is used to build each component's navigation.
     17 *
     18 * @since 2.6.0
     19 */
     20class BP_Core_Nav {
     21        /**
     22         * An associative array containing the nav items for the object ID.
     23         *
     24         * @since 2.6.0
     25         * @var array
     26         */
     27        protected $nav;
     28
     29        /**
     30         * The current object ID.
     31         *
     32         * @since 2.6.0
     33         * @var int
     34         */
     35        private $object_id;
     36
     37        /**
     38         * Initializes the Nav belonging to the specified object.
     39         *
     40         * @since 2.6.0
     41         *
     42         * @param int $object_id The item ID to build the nav for. Default is the displayed user ID.
     43         */
     44        public function __construct( $object_id = 0 ) {
     45                if ( empty( $object_id ) ) {
     46                        $this->object_id = (int) bp_displayed_user_id();
     47                } else {
     48                        $this->object_id = (int) $object_id;
     49                }
     50
     51                $this->nav[ $this->object_id ] = array();
     52        }
     53
     54        /**
     55         * Checks whether a nav item is set.
     56         *
     57         * @since 2.6.0
     58         *
     59         * @param  string $key The requested nav slug.
     60         * @return bool True if the nav item is set, false otherwise.
     61         */
     62        public function __isset( $key ) {
     63                return isset( $this->nav[ $this->object_id ][ $key ] );
     64        }
     65
     66        /**
     67         * Gets a nav item.
     68         *
     69         * @since 2.6.0
     70         *
     71         * @param  string $key The requested nav slug.
     72         * @return mixed The value corresponding to the requested nav item.
     73         */
     74        public function __get( $key ) {
     75                if ( ! isset( $this->nav[ $this->object_id ][ $key ] ) ) {
     76                        $this->nav[ $this->object_id ][ $key ] = null;
     77                }
     78
     79                return $this->nav[ $this->object_id ][ $key ];
     80        }
     81
     82        /**
     83         * Sets a nav item.
     84         *
     85         * @since 2.6.0
     86         *
     87         * @param  string  $key   The requested nav slug.
     88         * @param  mixed   $value The value of the nav item.
     89         */
     90        public function __set( $key, $value ) {
     91                if ( is_array( $value ) ) {
     92                        $value['primary'] = true;
     93                }
     94
     95                $this->nav[ $this->object_id ][ $key ] = new BP_Core_Nav_Item( $value );
     96        }
     97
     98        /**
     99         * Gets a specific nav item or array of nav items.
     100         *
     101         * @since 2.6.0
     102         *
     103         * @param  string $key The nav item slug to get. Optional.
     104         * @return mixed       An array of nav item, a single nav item, or null if none found.
     105         */
     106        public function get( $key = '' ) {
     107                $return = null;
     108
     109                // Return the requested nav item.
     110                if ( ! empty( $key ) ) {
     111                        if ( ! isset( $this->nav[ $this->object_id ][ $key ] ) ) {
     112                                $return = null;
     113                        } else {
     114                                $return = $this->nav[ $this->object_id ][ $key ];
     115                        }
     116
     117                // Return all nav item items.
     118                } else {
     119                        $return = $this->nav[ $this->object_id ];
     120                }
     121
     122                return $return;
     123        }
     124
     125        /**
     126         * Adds a new nav item.
     127         *
     128         * @since 2.6.0
     129         *
     130         * @param array $args The nav item's arguments.
     131         * @return BP_Core_Nav_Item
     132         */
     133        public function add_nav( $args ) {
     134                if ( empty( $args['slug'] ) ) {
     135                        return false;
     136                }
     137
     138                // We have a child and the parent exists.
     139                if ( ! empty( $args['parent_slug'] ) ) {
     140                        $slug              = $args['parent_slug'] . '/' . $args['slug'];
     141                        $args['secondary'] = true;
     142
     143                // This is a parent.
     144                } else {
     145                        $slug            = $args['slug'];
     146                        $args['primary'] = true;
     147                }
     148
     149                // Add to the nav.
     150                $this->nav[ $this->object_id ][ $slug ] = new BP_Core_Nav_Item( $args );
     151
     152                return $this->nav[ $this->object_id ][ $slug ];
     153        }
     154
     155        /**
     156         * Edits a nav item.
     157         *
     158         * @since 2.6.0
     159         *
     160         * @param array  $args        The nav item's arguments.
     161         * @param string $slug        The slug of the nav item.
     162         * @param string $parent_slug The slug of the parent nav item (required to edit a child).
     163         * @return BP_Core_Nav_Item
     164         */
     165        public function edit_nav( $args = array(), $slug = '', $parent_slug = '' ) {
     166                if ( empty( $slug ) ) {
     167                        return false;
     168                }
     169
     170                // We're editing a parent!
     171                if ( empty( $parent_slug ) ) {
     172                        $nav_items = $this->get_primary( array( 'slug' => $slug ), false );
     173
     174                        if ( ! $nav_items ) {
     175                                return false;
     176                        }
     177
     178                        $nav_item = reset( $nav_items );
     179                        $this->nav[ $this->object_id ][ $slug ] = new BP_Core_Nav_Item( wp_parse_args( $args, (array) $nav_item ) );
     180
     181                        // Return the edited object.
     182                        return $this->nav[ $this->object_id ][ $slug ];
     183
     184                // We're editing a child.
     185                } else {
     186                        $sub_items = $this->get_secondary( array( 'parent_slug' => $parent_slug, 'slug' => $slug ), false );
     187
     188                        if ( ! $sub_items ) {
     189                                return false;
     190                        }
     191
     192                        $sub_item = reset( $sub_items );
     193
     194                        $params = wp_parse_args( $args, (array) $sub_item );
     195
     196                        // When we have parents, it's for life, we can't change them!
     197                        if ( empty( $params['parent_slug'] ) || $parent_slug !== $params['parent_slug'] ) {
     198                                return false;
     199                        }
     200
     201                        $this->nav[ $this->object_id ][ $parent_slug . '/' . $slug ] = new BP_Core_Nav_Item( $params );
     202
     203                        // Return the edited object.
     204                        return $this->nav[ $this->object_id ][ $parent_slug . '/' . $slug ];
     205                }
     206        }
     207
     208        /**
     209         * Unset an item or a subitem of the nav.
     210         *
     211         * @since 2.6.0
     212         *
     213         * @param string $key     The slug of the main item.
     214         * @param string $sub_key The slug of the sub item.
     215         * @return bool|callable|array False on failure, the screen function(s) on success.
     216         */
     217        public function delete_nav( $slug, $parent_slug = '' ) {
     218                if ( empty( $slug ) ) {
     219                        return false;
     220                }
     221
     222                // We're deleting a child
     223                if ( ! empty( $parent_slug ) ) {
     224
     225                        // Validate the subnav
     226                        $sub_items = $this->get_secondary( array( 'parent_slug' => $parent_slug, 'slug' => $slug ), false );
     227
     228                        if ( ! $sub_items ) {
     229                                return false;
     230                        }
     231
     232                        $sub_item = reset( $sub_items );
     233
     234                        if ( empty( $sub_item->slug ) ) {
     235                                return false;
     236                        }
     237
     238                        // Delete the child
     239                        unset( $this->nav[ $this->object_id ][ $parent_slug . '/' . $slug ] );
     240
     241                        // Return the deleted item's screen function
     242                        return array( $sub_item->screen_function );
     243
     244                // We're deleting a parent
     245                } else {
     246                        // Validate the nav
     247                        $nav_items = $this->get_primary( array( 'slug' => $slug ), false );
     248
     249                        if ( ! $nav_items ) {
     250                                return false;
     251                        }
     252
     253                        $nav_item = reset( $nav_items );
     254
     255                        if ( empty( $nav_item->slug ) ) {
     256                                return false;
     257                        }
     258
     259                        $screen_functions = array( $nav_item->screen_function );
     260
     261                        // Life's unfair, children won't survive the parent :(
     262                        $sub_items = $this->get_secondary( array( 'parent_slug' => $nav_item->slug ), false );
     263
     264                        if ( ! empty( $sub_items ) ) {
     265                                foreach ( $sub_items as $sub_item ) {
     266                                        $screen_functions[] = $sub_item->screen_function;
     267
     268                                        // Delete the child
     269                                        unset( $this->nav[ $this->object_id ][ $nav_item->slug . '/' . $sub_item->slug ] );
     270                                }
     271                        }
     272
     273                        // Delete the parent.
     274                        unset( $this->nav[ $this->object_id ][ $nav_item->slug ] );
     275
     276                        // Return the deleted item's screen functions.
     277                        return array_unique( $screen_functions );
     278                }
     279        }
     280
     281        /**
     282         * Sorts a list of nav items.
     283         *
     284         * @since 2.6.0
     285         *
     286         * @param array $items The nav items to sort.
     287         * @return array
     288         */
     289        public function sort_nav( $items ) {
     290                $sorted = array();
     291
     292                foreach ( $items as $item ) {
     293                        // Default position
     294                        $position = 99;
     295
     296                        if ( isset( $item->position ) ) {
     297                                $position = (int) $item->position;
     298                        }
     299
     300                        // If position is already taken, move to the first next available
     301                        if ( isset( $sorted[ $position ] ) ) {
     302                                $sorted_keys = array_keys( $sorted );
     303
     304                                do {
     305                                        $position += 1;
     306                                } while ( in_array( $position, $sorted_keys ) );
     307                        }
     308
     309                        $sorted[ $position ] = $item;
     310                }
     311
     312                ksort( $sorted );
     313                return $sorted;
     314        }
     315
     316        /**
     317         * Gets the primary nav items.
     318         *
     319         * @since 2.6.0
     320         *
     321         * @param  array $args Filters to select the specific primary items. See wp_list_filter().
     322         * @param  bool  $sort True to sort the nav items. False otherwise.
     323         * @return array The list of primary objects nav
     324         */
     325        public function get_primary( $args = array(), $sort = true ) {
     326                $params = wp_parse_args( $args, array( 'primary' => true ) );
     327
     328                // This parameter is not overridable
     329                if ( empty( $params['primary'] ) ) {
     330                        return false;
     331                }
     332
     333                $primary_nav = wp_list_filter( $this->nav[ $this->object_id ], $params );
     334
     335                if ( ! $primary_nav ) {
     336                        return false;
     337                }
     338
     339                if ( true !== $sort ) {
     340                        return $primary_nav;
     341                }
     342
     343                return $this->sort_nav( $primary_nav );
     344        }
     345
     346        /**
     347         * Gets the secondary nav items.
     348         *
     349         * @since 2.6.0
     350         *
     351         * @param  array $args Filters to select the specific secondary items. See wp_list_filter().
     352         * @param  bool  $sort True to sort the nav items. False otherwise.
     353         * @return array The list of secondary objects nav
     354         */
     355        public function get_secondary( $args = array(), $sort = true ) {
     356                $params = wp_parse_args( $args, array( 'parent_slug' => '' ) );
     357
     358                // No need to search children if the parent is not set
     359                if ( empty( $params['parent_slug'] ) && empty( $params['secondary'] ) ) {
     360                        return false;
     361                }
     362
     363                $secondary_nav = wp_list_filter( $this->nav[ $this->object_id ], $params );
     364
     365                if ( ! $secondary_nav ) {
     366                        return false;
     367                }
     368
     369                if ( true !== $sort ) {
     370                        return $secondary_nav;
     371                }
     372
     373                return $this->sort_nav( $secondary_nav );
     374        }
     375
     376        /**
     377         * Gets a nested list of visible nav items.
     378         *
     379         * @since 2.6.0
     380         *
     381         * @return array The list of visible nav items.
     382         */
     383        public function get_item_nav() {
     384                $primary_nav_items = $this->get_primary( array( 'show_for_displayed_user' => true ) );
     385
     386                if ( $primary_nav_items ) {
     387                        foreach( $primary_nav_items as $key_nav => $primary_nav ) {
     388                                // Try to get the children
     389                                $children = $this->get_secondary( array( 'parent_slug' => $primary_nav->slug, 'user_has_access' => true ) );
     390
     391                                if ( $children ) {
     392                                        $primary_nav_items[ $key_nav ] = clone( $primary_nav );
     393                                        $primary_nav_items[ $key_nav ]->children = $children;
     394                                }
     395                        }
     396                }
     397
     398                return $primary_nav_items;
     399        }
     400}
  • src/bp-core/classes/class-bp-core.php

    diff --git src/bp-core/classes/class-bp-core.php src/bp-core/classes/class-bp-core.php
    index 3cdfc0e..e6cc35b 100644
    class BP_Core extends BP_Component { 
    254254                // bp-notifications instead.
    255255                $bp->core->table_name_notifications = $bp->table_prefix . 'bp_notifications';
    256256
     257                // Backward compatibility for plugins modifying the legacy bp_nav and bp_options_nav global properties.
     258                if ( buddypress()->do_nav_backcompat ) {
     259                        $bp->bp_nav         = new BP_Core_BP_Nav_BackCompat();
     260                        $bp->bp_options_nav = new BP_Core_BP_Options_Nav_BackCompat();
     261                }
     262
    257263                /**
    258264                 * Used to determine if user has admin rights on current content. If the
    259265                 * logged in user is viewing their own profile and wants to delete
  • src/bp-core/deprecated/2.6.php

    diff --git src/bp-core/deprecated/2.6.php src/bp-core/deprecated/2.6.php
    index acc5e23..1b1de5c 100644
    function bp_core_print_generation_time() { 
    2121
    2222        <?php
    2323}
     24
     25/**
     26 * Sort the navigation menu items.
     27 *
     28 * The sorting is split into a separate function because it can only happen
     29 * after all plugins have had a chance to register their navigation items.
     30 *
     31 * @since 1.0.0
     32 * @deprecated 2.6.0
     33 *
     34 * @return bool|null Returns false on failure.
     35 */
     36function bp_core_sort_nav_items() {
     37        _deprecated_function( __FUNCTION__, '2.6' );
     38}
     39
     40/**
     41 * Sort all subnavigation arrays.
     42 *
     43 * @since 1.1.0
     44 * @deprecated 2.6.0
     45 *
     46 * @return bool|null Returns false on failure.
     47 */
     48function bp_core_sort_subnav_items() {
     49        _deprecated_function( __FUNCTION__, '2.6' );
     50}
     51
     52/**
     53 * Remove a nav item from the navigation array.
     54 *
     55 * @since 1.0.0
     56 * @deprecated 2.6.0
     57 *
     58 * @param int $parent_id The slug of the parent navigation item.
     59 * @return bool Returns false on failure, ie if the nav item can't be found.
     60 */
     61function bp_core_remove_nav_item( $parent_id ) {
     62        $bp = buddypress();
     63
     64        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_nav_item' );
     65
     66        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     67
     68                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     69                        return bp_core_delete_nav_item( $parent_id, 'groups' );
     70                }
     71        }
     72
     73        return bp_core_delete_nav_item( $parent_id );
     74}
     75
     76/**
     77 * Remove a subnav item from the navigation array.
     78 *
     79 * @since 1.0.0
     80 * @deprecated 2.6.0
     81 *
     82 * @param string $parent_id The slug of the parent navigation item.
     83 * @param string $slug      The slug of the subnav item to be removed.
     84 */
     85function bp_core_remove_subnav_item( $parent_id, $slug ) {
     86        $bp = buddypress();
     87
     88        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_subnav_item' );
     89
     90        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     91
     92                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     93                        return bp_core_delete_subnav_item( $slug, $parent_id, 'groups' );
     94                }
     95        }
     96
     97        return bp_core_delete_subnav_item( $slug, $parent_id );
     98}
  • src/bp-groups/bp-groups-adminbar.php

    diff --git src/bp-groups/bp-groups-adminbar.php src/bp-groups/bp-groups-adminbar.php
    index f27f74e..6cef4b5 100644
    function bp_groups_group_admin_menu() { 
    4747        ) );
    4848
    4949        // Index of the Manage tabs parent slug.
    50         $nav_index = $bp->groups->current_group->slug . '_manage';
     50        $secondary_nav_items = $bp->groups->nav->get_secondary( array( 'parent_slug' => $bp->groups->current_group->slug . '_manage' ) );
    5151
    5252        // Check if current group has Manage tabs.
    53         if ( empty( $bp->bp_options_nav[ $nav_index ] ) ) {
     53        if ( ! $secondary_nav_items ) {
    5454                return;
    5555        }
    5656
    5757        // Build the Group Admin menus.
    58         foreach ( $bp->bp_options_nav[ $nav_index ] as $menu ) {
     58        foreach ( $secondary_nav_items as $menu ) {
    5959                /**
    6060                 * Should we add the current manage link in the Group's "Edit" Admin Bar menu ?
    6161                 *
    function bp_groups_group_admin_menu() { 
    6363                 * to also add the link to the "edit screen" of their group component. To do so, set the
    6464                 * the 'show_in_admin_bar' argument of your edit screen to true
    6565                 */
    66                 if ( $menu['show_in_admin_bar'] ) {
    67                         $title = sprintf( _x( 'Edit Group %s', 'Group WP Admin Bar manage links', 'buddypress' ), $menu['name'] );
     66                if ( $menu->show_in_admin_bar ) {
     67                        $title = sprintf( _x( 'Edit Group %s', 'Group WP Admin Bar manage links', 'buddypress' ), $menu->name );
    6868
    6969                        // Title is specific for delete.
    70                         if ( 'delete-group' == $menu['slug'] ) {
    71                                 $title = sprintf( _x( '%s Group', 'Group WP Admin Bar delete link', 'buddypress' ), $menu['name'] );
     70                        if ( 'delete-group' == $menu->slug ) {
     71                                $title = sprintf( _x( '%s Group', 'Group WP Admin Bar delete link', 'buddypress' ), $menu->name );
    7272                        }
    7373
    7474                        $wp_admin_bar->add_menu( array(
    7575                                'parent' => $bp->group_admin_menu_id,
    76                                 'id'     => $menu['slug'],
     76                                'id'     => $menu->slug,
    7777                                'title'  => $title,
    78                                 'href'   => bp_get_groups_action_link( 'admin/' . $menu['slug'] )
     78                                'href'   => bp_get_groups_action_link( 'admin/' . $menu->slug )
    7979                        ) );
    8080                }
    8181        }
  • src/bp-groups/classes/class-bp-group-extension.php

    diff --git src/bp-groups/classes/class-bp-group-extension.php src/bp-groups/classes/class-bp-group-extension.php
    index 5709b0b..c0ae5df 100644
    class BP_Group_Extension { 
    737737                                'screen_function' => array( &$this, '_display_hook' ),
    738738                                'user_has_access' => $user_can_see_nav_item,
    739739                                'no_access_url'   => $group_permalink,
    740                         ) );
     740                        ), 'groups' );
    741741                }
    742742
    743743                // If the user can visit the screen, we register it.
    class BP_Group_Extension { 
    752752                                'screen_function' => array( &$this, '_display_hook' ),
    753753                                'user_has_access' => $user_can_visit,
    754754                                'no_access_url'   => $group_permalink,
    755                         ) );
     755                        ), 'groups' );
    756756
    757757                        // When we are viewing the extension display page, set the title and options title.
    758758                        if ( bp_is_current_action( $this->slug ) ) {
    class BP_Group_Extension { 
    967967                }
    968968
    969969                // Add the tab to the manage navigation.
    970                 bp_core_new_subnav_item( $subnav_args );
     970                bp_core_new_subnav_item( $subnav_args, 'groups' );
    971971
    972972                // Catch the edit screen and forward it to the plugin template.
    973973                if ( bp_is_groups_component() && bp_is_current_action( 'admin' ) && bp_is_action_variable( $screen['slug'], 0 ) ) {
  • src/bp-groups/classes/class-bp-groups-component.php

    diff --git src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
    index 355ab8c..994a584 100644
    class BP_Groups_Component extends BP_Component { 
    253253                        // Check once if the current group has a custom front template.
    254254                        $this->current_group->front_template = bp_groups_get_front_template( $this->current_group );
    255255
     256                        // Initialize the nav for the groups component.
     257                        $this->nav = new BP_Core_Nav( $this->current_group->id );
     258
    256259                // Set current_group to 0 to prevent debug errors.
    257260                } else {
    258261                        $this->current_group = 0;
    class BP_Groups_Component extends BP_Component { 
    496499                        // Reset sub nav.
    497500                        $sub_nav = array();
    498501
    499                         // Add 'Groups' to the main navigation.
    500                         $main_nav = array(
     502                        bp_core_new_nav_item( array(
    501503                                'name'                => __( 'Memberships', 'buddypress' ),
    502504                                'slug'                => $this->current_group->slug,
    503505                                'position'            => -1, // Do not show in BuddyBar.
    504506                                'screen_function'     => 'groups_screen_group_home',
    505507                                'default_subnav_slug' => $this->default_extension,
    506508                                'item_css_id'         => $this->id
    507                         );
     509                        ), 'groups' );
    508510
    509511                        $group_link = bp_get_group_permalink( $this->current_group );
    510512
    class BP_Groups_Component extends BP_Component { 
    675677                                ), $default_params );
    676678                        }
    677679
    678                         parent::setup_nav( $main_nav, $sub_nav );
     680                        foreach ( $sub_nav as $nav ) {
     681                                bp_core_new_subnav_item( $nav, 'groups' );
     682                        }
    679683                }
    680684
    681685                if ( isset( $this->current_group->user_has_access ) ) {
  • src/bp-loader.php

    diff --git src/bp-loader.php src/bp-loader.php
    index 4a744c4..f89d7b3 100644
    class BuddyPress { 
    109109         */
    110110        public $do_autoload = false;
    111111
     112        /**
     113         * Whether to load backward compatibility classes for navigation globals.
     114         *
     115         * @since 2.6.0
     116         * @var bool
     117         */
     118        public $do_nav_backcompat = false;
     119
    112120        /** Option Overload *******************************************************/
    113121
    114122        /**
    class BuddyPress { 
    434442                /** Post types and taxonomies *****************************************/
    435443                $this->email_post_type     = apply_filters( 'bp_email_post_type', 'bp-email' );
    436444                $this->email_taxonomy_type = apply_filters( 'bp_email_tax_type', 'bp-email-type' );
     445
     446                /** Navigation backward compatibility *********************************/
     447                if ( interface_exists( 'ArrayAccess', false ) ) {
     448                        $this->do_nav_backcompat = true;
     449                }
    437450        }
    438451
    439452        /**
  • src/bp-members/bp-members-template.php

    diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
    index bffd155..038ec06 100644
    function bp_get_loggedin_user_nav() { 
    12901290        $bp = buddypress();
    12911291
    12921292        // Loop through each navigation item.
    1293         foreach( (array) $bp->bp_nav as $nav_item ) {
     1293        foreach( (array) $bp->members->nav->get_primary() as $nav_item ) {
    12941294
    12951295                $selected = '';
    12961296
    12971297                // If the current component matches the nav item id, then add a highlight CSS class.
    1298                 if ( !bp_is_directory() && !empty( $bp->active_components[bp_current_component()] ) && $bp->active_components[bp_current_component()] == $nav_item['css_id'] ) {
     1298                if ( !bp_is_directory() && !empty( $bp->active_components[bp_current_component()] ) && $bp->active_components[bp_current_component()] == $nav_item->css_id ) {
    12991299                        $selected = ' class="current selected"';
    13001300                }
    13011301
    function bp_get_loggedin_user_nav() { 
    13071307                        $selected = '';
    13081308
    13091309                        if ( bp_is_active( 'friends' ) ) {
    1310                                 if ( $nav_item['css_id'] == $bp->friends->id ) {
     1310                                if ( $nav_item->css_id == $bp->friends->id ) {
    13111311                                        if ( friends_check_friendship( bp_loggedin_user_id(), bp_displayed_user_id() ) ) {
    13121312                                                $selected = ' class="current selected"';
    13131313                                        }
    function bp_get_loggedin_user_nav() { 
    13161316                }
    13171317
    13181318                // Echo out the final list item.
    1319                 echo apply_filters_ref_array( 'bp_get_loggedin_user_nav_' . $nav_item['css_id'], array( '<li id="li-nav-' . $nav_item['css_id'] . '" ' . $selected . '><a id="my-' . $nav_item['css_id'] . '" href="' . $nav_item['link'] . '">' . $nav_item['name'] . '</a></li>', &$nav_item ) );
     1319                echo apply_filters_ref_array( 'bp_get_loggedin_user_nav_' . $nav_item->css_id, array( '<li id="li-nav-' . $nav_item->css_id . '" ' . $selected . '><a id="my-' . $nav_item->css_id . '" href="' . $nav_item->link . '">' . $nav_item->name . '</a></li>', &$nav_item ) );
    13201320        }
    13211321
    13221322        // Always add a log out list item to the end of the navigation.
    function bp_get_loggedin_user_nav() { 
    13331333function bp_get_displayed_user_nav() {
    13341334        $bp = buddypress();
    13351335
    1336         foreach ( (array) $bp->bp_nav as $user_nav_item ) {
    1337                 if ( empty( $user_nav_item['show_for_displayed_user'] ) && !bp_is_my_profile() )
     1336        foreach ( $bp->members->nav->get_primary() as $user_nav_item ) {
     1337                if ( empty( $user_nav_item->show_for_displayed_user ) && ! bp_is_my_profile() ) {
    13381338                        continue;
     1339                }
    13391340
    13401341                $selected = '';
    1341                 if ( bp_is_current_component( $user_nav_item['slug'] ) ) {
     1342                if ( bp_is_current_component( $user_nav_item->slug ) ) {
    13421343                        $selected = ' class="current selected"';
    13431344                }
    13441345
    13451346                if ( bp_loggedin_user_domain() ) {
    1346                         $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $user_nav_item['link'] );
     1347                        $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $user_nav_item->link );
    13471348                } else {
    1348                         $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item['link'] );
     1349                        $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item->link );
    13491350                }
    13501351
    13511352                /**
    function bp_get_displayed_user_nav() { 
    13591360                 * @param array  $user_nav_item Array holding parts used to construct tab list item.
    13601361                 *                              Passed by reference.
    13611362                 */
    1362                 echo apply_filters_ref_array( 'bp_get_displayed_user_nav_' . $user_nav_item['css_id'], array( '<li id="' . $user_nav_item['css_id'] . '-personal-li" ' . $selected . '><a id="user-' . $user_nav_item['css_id'] . '" href="' . $link . '">' . $user_nav_item['name'] . '</a></li>', &$user_nav_item ) );
     1363                echo apply_filters_ref_array( 'bp_get_displayed_user_nav_' . $user_nav_item->css_id, array( '<li id="' . $user_nav_item->css_id . '-personal-li" ' . $selected . '><a id="user-' . $user_nav_item->css_id . '" href="' . $link . '">' . $user_nav_item->name . '</a></li>', &$user_nav_item ) );
    13631364        }
    13641365}
    13651366
  • src/bp-members/classes/class-bp-members-component.php

    diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php
    index 92a2c85..edf49a4 100644
    class BP_Members_Component extends BP_Component { 
    150150                // The domain for the user currently being displayed.
    151151                $bp->displayed_user->domain   = bp_core_get_user_domain( bp_displayed_user_id() );
    152152
     153                // Initialize the nav for the members component.
     154                $this->nav = new BP_Core_Nav();
     155
    153156                /** Signup ***********************************************************
    154157                 */
    155158
  • src/bp-messages/bp-messages-screens.php

    diff --git src/bp-messages/bp-messages-screens.php src/bp-messages/bp-messages-screens.php
    index 2be4937..0e92210 100644
    function messages_screen_conversation() { 
    132132        $class    = ( 0 === $count ) ? 'no-count' : 'count';
    133133        $nav_name = sprintf( __( 'Messages <span class="%s">%s</span>', 'buddypress' ), esc_attr( $class ), bp_core_number_format( $count ) );
    134134
    135         $bp->bp_nav[ $bp->messages->slug ]['name'] = $nav_name;
     135        // Edit the Navigation name.
     136        $bp->members->nav->edit_nav( array(
     137                'name' => $nav_name,
     138        ), $bp->messages->slug );
    136139
    137140        /**
    138141         * Fires right before the loading of the Messages view screen template file.
  • src/bp-settings/bp-settings-actions.php

    diff --git src/bp-settings/bp-settings-actions.php src/bp-settings/bp-settings-actions.php
    index f377ff6..6a68868 100644
    add_action( 'bp_actions', 'bp_settings_verify_email_change' ); 
    488488 */
    489489function bp_settings_remove_email_subnav() {
    490490        if ( ! has_action( 'bp_notification_settings' ) ) {
    491                 bp_core_remove_subnav_item( BP_SETTINGS_SLUG, 'notifications' );
     491                bp_core_delete_subnav_item( 'notifications', BP_SETTINGS_SLUG );
    492492        }
    493493}
    494494add_action( 'bp_actions', 'bp_settings_remove_email_subnav' );
  • src/bp-xprofile/classes/class-bp-xprofile-component.php

    diff --git src/bp-xprofile/classes/class-bp-xprofile-component.php src/bp-xprofile/classes/class-bp-xprofile-component.php
    index 87689b1..f25edec 100644
    class BP_XProfile_Component extends BP_Component { 
    302302                        'screen_function' => 'bp_xprofile_screen_settings',
    303303                        'position'        => 30,
    304304                        'user_has_access' => bp_core_can_edit_settings()
    305                 ) );
     305                ), 'members' );
    306306        }
    307307
    308308        /**
  • deleted file tests/phpunit/testcases/core/nav.php

    diff --git tests/phpunit/testcases/core/nav.php tests/phpunit/testcases/core/nav.php
    deleted file mode 100644
    index 721217d..0000000
    + -  
    1 <?php
    2 
    3 /**
    4  * @group core
    5  * @group nav
    6  */
    7 class BP_Tests_Core_Nav extends BP_UnitTestCase {
    8 
    9         /**
    10          * @group bp_core_sort_nav_items
    11          */
    12         public function test_bp_core_sort_nav_items() {
    13                 $bp_nav = buddypress()->bp_nav;
    14 
    15                 $u = $this->factory->user->create();
    16                 $old_current_user = get_current_user_id();
    17                 $this->set_current_user( $u );
    18 
    19                 $this->go_to( bp_core_get_user_domain( $u ) );
    20 
    21                 bp_core_new_nav_item( array(
    22                         'name'                    => 'Foo',
    23                         'slug'                    => 'foo',
    24                         'position'                => 25,
    25                         'screen_function'         => 'foo_screen_function',
    26                         'default_subnav_slug'     => 'foo-sub'
    27                 ) );
    28 
    29                 $expected = array(
    30                         'name'                    => 'Foo',
    31                         'slug'                    => 'foo',
    32                         'link'                    => trailingslashit( bp_core_get_user_domain( $u ) . 'foo' ),
    33                         'css_id'                  => 'foo',
    34                         'show_for_displayed_user' => true,
    35                         'position'                => 25,
    36                         'screen_function'         => 'foo_screen_function',
    37                         'default_subnav_slug'     => 'foo-sub'
    38                 );
    39 
    40                 bp_core_sort_nav_items();
    41 
    42                 $this->assertSame( buddypress()->bp_nav[25], $expected );
    43 
    44                 // Clean up
    45                 buddypress()->bp_nav = $bp_nav;
    46                 $this->set_current_user( $old_current_user );
    47         }
    48 
    49         /**
    50          * @group bp_core_sort_subnav_items
    51          */
    52         public function test_bp_core_sort_subnav_items() {
    53                 $bp_options_nav = buddypress()->bp_options_nav;
    54 
    55                 $u = $this->factory->user->create();
    56                 $old_current_user = get_current_user_id();
    57                 $this->set_current_user( $u );
    58 
    59                 $user_domain = bp_core_get_user_domain( $u );
    60 
    61                 $this->go_to( $user_domain );
    62 
    63                 bp_core_new_subnav_item( array(
    64                         'name'            => 'Foo',
    65                         'slug'            => 'foo',
    66                         'parent_url'      => trailingslashit( $user_domain . 'foo' ),
    67                         'parent_slug'     => 'foo',
    68                         'screen_function' => 'foo_screen_function',
    69                         'position'        => 10
    70                 ) );
    71 
    72                 bp_core_sort_subnav_items();
    73 
    74                 $expected = array(
    75                         'name'              => 'Foo',
    76                         'link'              => trailingslashit( $user_domain . 'foo/foo' ),
    77                         'slug'              => 'foo',
    78                         'css_id'            => 'foo',
    79                         'position'          => 10,
    80                         'user_has_access'   => true,
    81                         'no_access_url'     => '',
    82                         'screen_function'   => 'foo_screen_function',
    83                         'show_in_admin_bar' => false,
    84                 );
    85 
    86                 $this->assertSame( buddypress()->bp_options_nav['foo'][10], $expected );
    87 
    88                 // Clean up
    89                 buddypress()->bp_options_nav = $bp_options_nav;
    90                 $this->set_current_user( $old_current_user );
    91         }
    92 }
  • new file tests/phpunit/testcases/core/nav/backCompat.php

    diff --git tests/phpunit/testcases/core/nav/backCompat.php tests/phpunit/testcases/core/nav/backCompat.php
    new file mode 100644
    index 0000000..5f5f017
    - +  
     1<?php
     2
     3/**
     4 * @group core
     5 * @group nav
     6 * @ticket BP6534
     7 * @expectedIncorrectUsage bp_nav
     8 */
     9class BP_Core_Nav_BackCompat extends BP_UnitTestCase {
     10        protected $bp_nav;
     11        protected $bp_options_nav;
     12
     13        public function setUp() {
     14                parent::setUp();
     15                $this->bp_nav = buddypress()->bp_nav;
     16                $this->bp_options_nav = buddypress()->bp_options_nav;
     17        }
     18
     19        public function tearDown() {
     20                buddypress()->bp_nav = $this->bp_nav;
     21                buddypress()->bp_options_nav = $this->bp_options_nav;
     22                parent::tearDown();
     23        }
     24
     25        protected function create_nav_items() {
     26                bp_core_new_nav_item( array(
     27                        'name'                => 'Foo',
     28                        'slug'                => 'foo',
     29                        'position'            => 25,
     30                        'screen_function'     => 'foo_screen_function',
     31                        'default_subnav_slug' => 'foo-subnav'
     32                ) );
     33
     34                bp_core_new_subnav_item( array(
     35                        'name'            => 'Foo Subnav',
     36                        'slug'            => 'foo-subnav',
     37                        'parent_url'      => 'example.com/foo',
     38                        'parent_slug'     => 'foo',
     39                        'screen_function' => 'foo_screen_function',
     40                        'position'        => 10
     41                ) );
     42        }
     43
     44        /**
     45         * Create a group, set up nav item, and go to the group.
     46         */
     47        protected function set_up_group() {
     48                $g = $this->factory->group->create( array(
     49                        'slug' => 'testgroup',
     50                ) );
     51
     52                $group = groups_get_group( array( 'group_id' => $g ) );
     53                $group_permalink = bp_get_group_permalink( $group );
     54
     55                $this->go_to( $group_permalink );
     56
     57                bp_core_new_subnav_item( array(
     58                        'name'            => 'Foo',
     59                        'slug'            => 'foo',
     60                        'parent_url'      => $group_permalink,
     61                        'parent_slug'     => 'testgroup',
     62                        'screen_function' => 'foo_screen_function',
     63                        'position'        => 10
     64                ), 'groups' );
     65        }
     66
     67        public function test_bp_nav_isset() {
     68                $this->create_nav_items();
     69
     70                $bp = buddypress();
     71
     72                $this->assertTrue( isset( $bp->bp_nav ) );
     73                $this->assertTrue( isset( $bp->bp_nav['foo'] ) );
     74                $this->assertTrue( isset( $bp->bp_nav['foo']['name'] ) );
     75        }
     76
     77        public function test_bp_nav_unset() {
     78                $this->create_nav_items();
     79
     80                $bp = buddypress();
     81
     82                // No support for this - it would create a malformed nav item.
     83                /*
     84                unset( $bp->bp_nav['foo']['css_id'] );
     85                $this->assertFalse( isset( $bp->bp_nav['foo']['css_id'] ) );
     86                */
     87
     88                unset( $bp->bp_nav['foo'] );
     89                $this->assertFalse( isset( $bp->bp_nav['foo'] ) );
     90        }
     91
     92        public function test_bp_nav_get() {
     93                $this->create_nav_items();
     94
     95                $bp = buddypress();
     96
     97                $foo = $bp->bp_nav['foo'];
     98                $this->assertSame( 'Foo', $foo['name'] );
     99
     100                $this->assertSame( 'Foo', $bp->bp_nav['foo']['name'] );
     101        }
     102
     103        public function test_bp_nav_set() {
     104                $this->create_nav_items();
     105
     106                $bp = buddypress();
     107
     108                $bp->bp_nav['foo']['name'] = 'Bar';
     109
     110                $nav = bp_get_nav_menu_items();
     111
     112                foreach ( $nav as $_nav ) {
     113                        if ( 'foo' === $_nav->css_id ) {
     114                                $found = $_nav;
     115                                break;
     116                        }
     117                }
     118
     119                $this->assertSame( 'Bar', $found->name );
     120        }
     121
     122        public function test_bp_options_nav_isset() {
     123                $this->create_nav_items();
     124
     125                $bp = buddypress();
     126
     127                $this->assertTrue( isset( $bp->bp_options_nav ) );
     128                $this->assertTrue( isset( $bp->bp_options_nav['foo'] ) );
     129                $this->assertTrue( isset( $bp->bp_options_nav['foo']['foo-subnav'] ) );
     130                $this->assertTrue( isset( $bp->bp_options_nav['foo']['foo-subnav']['name'] ) );
     131        }
     132
     133        public function test_bp_options_nav_unset() {
     134                $this->create_nav_items();
     135
     136                $bp = buddypress();
     137
     138                // No support for this - it would create a malformed nav item.
     139                /*
     140                unset( $bp->bp_options_nav['foo']['foo-subnav']['user_has_access'] );
     141                $this->assertFalse( isset( $bp->bp_options_nav['foo']['foo-subnav']['user_has_access'] ) );
     142                */
     143
     144                unset( $bp->bp_options_nav['foo']['foo-subnav'] );
     145                $this->assertFalse( isset( $bp->bp_options_nav['foo']['foo-subnav'] ) );
     146
     147                // Make sure the parent nav hasn't been wiped out.
     148                $this->assertTrue( isset( $bp->bp_options_nav['foo'] ) );
     149
     150                unset( $bp->bp_options_nav['foo'] );
     151                $this->assertFalse( isset( $bp->bp_options_nav['foo'] ) );
     152        }
     153
     154        public function test_bp_options_nav_get() {
     155                $this->create_nav_items();
     156
     157                $bp = buddypress();
     158
     159                $foo_subnav = $bp->bp_options_nav['foo']['foo-subnav'];
     160                $this->assertSame( 'Foo Subnav', $foo_subnav['name'] );
     161
     162                $this->assertSame( 'Foo Subnav', $bp->bp_options_nav['foo']['foo-subnav']['name'] );
     163        }
     164
     165        public function test_bp_options_nav_set() {
     166                $this->create_nav_items();
     167
     168                $bp = buddypress();
     169
     170                $bp->bp_options_nav['foo']['foo-subnav']['name'] = 'Bar';
     171                $nav = bp_get_nav_menu_items();
     172
     173                foreach ( $nav as $_nav ) {
     174                        if ( 'foo-subnav' === $_nav->css_id ) {
     175                                $found = $_nav;
     176                                break;
     177                        }
     178                }
     179
     180                $this->assertSame( 'Bar', $found->name );
     181
     182                $subnav = array(
     183                        'name' => 'Bar',
     184                        'css_id' => 'bar-id',
     185                        'link' => 'bar-link',
     186                        'slug' => 'bar-slug',
     187                        'user_has_access' => true,
     188                );
     189                $bp->bp_options_nav['foo']['foo-subnav'] = $subnav;
     190                $nav = bp_get_nav_menu_items();
     191
     192                foreach ( $nav as $_nav ) {
     193                        if ( 'bar-id' === $_nav->css_id ) {
     194                                $found = $_nav;
     195                                break;
     196                        }
     197                }
     198
     199                $this->assertSame( 'Bar', $found->name );
     200        }
     201
     202        /**
     203         * @group groups
     204         */
     205        public function test_bp_options_nav_isset_group_nav() {
     206                $this->set_up_group();
     207
     208                $bp = buddypress();
     209
     210                $this->assertTrue( isset( $bp->bp_options_nav ) );
     211                $this->assertTrue( isset( $bp->bp_options_nav['testgroup'] ) );
     212                $this->assertTrue( isset( $bp->bp_options_nav['testgroup']['foo'] ) );
     213                $this->assertTrue( isset( $bp->bp_options_nav['testgroup']['foo']['name'] ) );
     214        }
     215
     216        /**
     217         * @group groups
     218         */
     219        public function test_bp_options_nav_unset_group_nav() {
     220                $this->set_up_group();
     221
     222                $bp = buddypress();
     223
     224                // No support for this - it would create a malformed nav item.
     225                /*
     226                unset( $bp->bp_options_nav['testgroup']['foo']['user_has_access'] );
     227                $this->assertFalse( isset( $bp->bp_options_nav['testgroup']['foo']['user_has_access'] ) );
     228                */
     229
     230                unset( $bp->bp_options_nav['testgroup']['foo'] );
     231                $this->assertFalse( isset( $bp->bp_options_nav['testgroup']['foo'] ) );
     232
     233                unset( $bp->bp_options_nav['testgroup'] );
     234                $this->assertFalse( isset( $bp->bp_options_nav['testgroup'] ) );
     235        }
     236
     237        /**
     238         * @group groups
     239         */
     240        public function test_bp_options_nav_get_group_nav() {
     241                $this->set_up_group();
     242
     243                $bp = buddypress();
     244
     245                $foo = $bp->bp_options_nav['testgroup']['foo'];
     246                $this->assertSame( 'Foo', $foo['name'] );
     247
     248                $this->assertSame( 'Foo', $bp->bp_options_nav['testgroup']['foo']['name'] );
     249        }
     250
     251        /**
     252         * @group groups
     253         */
     254        public function test_bp_options_nav_set_group_nav() {
     255                $this->set_up_group();
     256
     257                $bp = buddypress();
     258
     259                $bp->bp_options_nav['testgroup']['foo']['name'] = 'Bar';
     260                $nav = bp_get_nav_menu_items( 'groups' );
     261
     262                foreach ( $nav as $_nav ) {
     263                        if ( 'foo' === $_nav->css_id ) {
     264                                $found = $_nav;
     265                                break;
     266                        }
     267                }
     268
     269                $this->assertSame( 'Bar', $found->name );
     270
     271                $subnav = array(
     272                        'name' => 'Bar',
     273                        'css_id' => 'bar-id',
     274                        'link' => 'bar-link',
     275                        'slug' => 'bar-slug',
     276                        'user_has_access' => true,
     277                );
     278                $bp->bp_options_nav['testgroup']['foo'] = $subnav;
     279                $nav = bp_get_nav_menu_items( 'groups' );
     280
     281                foreach ( $nav as $_nav ) {
     282                        if ( 'bar-id' === $_nav->css_id ) {
     283                                $found = $_nav;
     284                                break;
     285                        }
     286                }
     287
     288                $this->assertSame( 'Bar', $found->name );
     289        }
     290
     291        /**
     292         * @group groups
     293         */
     294        public function test_bp_core_new_subnav_item_should_work_in_group_context() {
     295                $this->set_up_group();
     296
     297                bp_core_new_subnav_item( array(
     298                        'name' => 'Foo Subnav',
     299                        'slug' => 'foo-subnav',
     300                        'parent_slug' => bp_get_current_group_slug(),
     301                        'parent_url' => bp_get_group_permalink( groups_get_current_group() ),
     302                        'screen_function' => 'foo_subnav',
     303                ) );
     304
     305                $bp = buddypress();
     306
     307                // Touch bp_nav since we told PHPUnit it was expectedDeprecated.
     308                $f = $bp->bp_options_nav[ bp_get_current_group_slug() ];
     309
     310                $nav = bp_get_nav_menu_items( 'groups' );
     311
     312                foreach ( $nav as $_nav ) {
     313                        if ( 'foo-subnav' === $_nav->css_id ) {
     314                                $found = $_nav;
     315                                break;
     316                        }
     317                }
     318
     319                $this->assertSame( 'Foo Subnav', $found->name );
     320        }
     321}
  • tests/phpunit/testcases/core/nav/bpCoreMaybeHookNewSubnavScreenFunction.php

    diff --git tests/phpunit/testcases/core/nav/bpCoreMaybeHookNewSubnavScreenFunction.php tests/phpunit/testcases/core/nav/bpCoreMaybeHookNewSubnavScreenFunction.php
    index 2ebc74c..41fed2a 100644
    class BP_Tests_Core_Nav_BpCoreMaybeHookNewSubnavScreenFunction extends BP_UnitTe 
    8282                $old_bp_nav = buddypress()->bp_nav;
    8383                $old_default_component = buddypress()->default_component;
    8484                buddypress()->default_component = 'foo';
    85                 buddypress()->bp_nav = array(
    86                         'foo' => array(
    87                                 'show_for_displayed_user' => true,
    88                         ),
    89                 );
     85
     86                bp_core_new_nav_item( array(
     87                        'slug' => 'foo',
     88                        'name' => 'Foo',
     89                        'screen_function' => 'foo',
     90                        'default_subnav_item' => 'bar',
     91                ) );
    9092
    9193                $subnav_item = array(
    9294                        'user_has_access' => false,
    class BP_Tests_Core_Nav_BpCoreMaybeHookNewSubnavScreenFunction extends BP_UnitTe 
    9496
    9597                // Just test relevant info
    9698                $found = bp_core_maybe_hook_new_subnav_screen_function( $subnav_item );
    97                 $this->assertSame( 'failure', $found['status'] );
    98                 $this->assertSame( bp_core_get_user_domain( $u2 ), $found['redirect_args']['root'] );
    9999
    100100                // Clean up
    101101                $this->set_current_user( $old_current_user );
    102102                buddypress()->default_component = $old_default_component;
    103103                buddypress()->bp_nav = $old_bp_nav;
     104
     105                $this->assertSame( 'failure', $found['status'] );
     106                $this->assertSame( bp_core_get_user_domain( $u2 ), $found['redirect_args']['root'] );
    104107        }
    105108
    106109        public function test_user_has_access_false_user_logged_in_others_profile_default_component_not_accessible() {
    class BP_Tests_Core_Nav_BpCoreMaybeHookNewSubnavScreenFunction extends BP_UnitTe 
    114117                $old_bp_nav = buddypress()->bp_nav;
    115118                $old_default_component = buddypress()->default_component;
    116119                buddypress()->default_component = 'foo';
    117                 buddypress()->bp_nav = array(
    118                         'foo' => array(
    119                                 'show_for_displayed_user' => false,
    120                         ),
    121                 );
     120
     121                bp_core_new_nav_item( array(
     122                        'slug' => 'foo',
     123                        'name' => 'Foo',
     124                        'screen_function' => 'foo',
     125                        'default_subnav_item' => 'bar',
     126                        'show_for_displayed_user' => false,
     127                ) );
    122128
    123129                $subnav_item = array(
    124130                        'user_has_access' => false,
    class BP_Tests_Core_Nav_BpCoreMaybeHookNewSubnavScreenFunction extends BP_UnitTe 
    126132
    127133                // Just test relevant info
    128134                $found = bp_core_maybe_hook_new_subnav_screen_function( $subnav_item );
    129                 $this->assertSame( 'failure', $found['status'] );
    130                 $this->assertSame( bp_core_get_user_domain( $u2 ) . bp_get_activity_slug() . '/', $found['redirect_args']['root'] );
    131135
    132136                // Clean up
    133137                $this->set_current_user( $old_current_user );
    134138                buddypress()->default_component = $old_default_component;
    135139                buddypress()->bp_nav = $old_bp_nav;
     140
     141                $this->assertSame( 'failure', $found['status'] );
     142                $this->assertSame( bp_core_get_user_domain( $u2 ) . bp_get_activity_slug() . '/', $found['redirect_args']['root'] );
    136143        }
    137144
    138145        public function test_user_has_access_false_user_logged_in_group() {
  • tests/phpunit/testcases/core/nav/bpCoreNewNavItem.php

    diff --git tests/phpunit/testcases/core/nav/bpCoreNewNavItem.php tests/phpunit/testcases/core/nav/bpCoreNewNavItem.php
    index b6f6439..884a8a8 100644
     
    55 */
    66class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase {
    77
     8        /**
     9         * @expectedIncorrectUsage bp_nav
     10         */
    811        public function test_user_nav() {
    912                $bp_nav = buddypress()->bp_nav;
    1013
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    3336                        'default_subnav_slug'     => 'foo-sub'
    3437                );
    3538
    36                 $this->assertSame( buddypress()->bp_nav['foo'], $expected );
     39                foreach ( $expected as $k => $v ) {
     40                        $this->assertEquals( $v, buddypress()->bp_nav['foo'][ $k ] );
     41                }
    3742
    3843                // Clean up
    3944                buddypress()->bp_nav = $bp_nav;
    4045                $this->set_current_user( $old_current_user );
    4146        }
    4247
     48        /**
     49         * @expectedIncorrectUsage bp_nav
     50         */
    4351        public function test_group_nav() {
    4452                $bp_nav = buddypress()->bp_nav;
    4553
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    8997                $this->assertFalse( bp_core_new_nav_item( $args ) );
    9098        }
    9199
     100        /**
     101         * @expectedIncorrectUsage bp_nav
     102         */
    92103        public function test_css_id_should_fall_back_on_slug() {
    93104                $args = array(
    94105                        'name' => 'Foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    99110                $this->assertSame( 'foo', buddypress()->bp_nav['foo']['css_id'] );
    100111        }
    101112
     113        /**
     114         * @expectedIncorrectUsage bp_nav
     115         */
    102116        public function test_css_id_should_be_respected() {
    103117                $args = array(
    104118                        'name' => 'Foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    124138                $this->assertFalse( $retval );
    125139        }
    126140
     141        /**
     142         * @expectedIncorrectUsage bp_nav
     143         */
    127144        public function test_existence_of_access_protected_user_nav() {
    128145                $bp_nav = buddypress()->bp_nav;
    129146
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    145162                        'default_subnav_slug'     => 'general'
    146163                );
    147164
    148                 $this->assertSame( buddypress()->bp_nav['settings'], $expected );
     165                foreach ( $expected as $k => $v ) {
     166                        $this->assertEquals( $v, buddypress()->bp_nav['settings'][ $k ] );
     167                }
    149168
    150169                // Clean up
    151170                buddypress()->bp_nav = $bp_nav;
    152171                $this->set_current_user( $old_current_user );
    153172        }
    154173
     174        /**
     175         * @expectedIncorrectUsage bp_nav
     176         */
    155177        public function test_creation_of_access_protected_user_nav() {
    156178                // The nav item must be added to bp_nav, even if the current user
    157179                // can't visit that nav item.
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    184206                        'default_subnav_slug'     => 'woof-one'
    185207                );
    186208
    187                 $this->assertSame( buddypress()->bp_nav['woof'], $expected );
     209                foreach ( $expected as $k => $v ) {
     210                        $this->assertEquals( $v, buddypress()->bp_nav['woof'][ $k ] );
     211                }
    188212
    189213                // Clean up
    190214                buddypress()->bp_nav = $bp_nav;
  • tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php

    diff --git tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php
    index cf07a2f..45ce3c5 100644
     
    55 */
    66class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase {
    77
     8        /**
     9         * @expectedIncorrectUsage bp_nav
     10         */
    811        public function test_user_subnav() {
    912                $bp_options_nav = buddypress()->bp_options_nav;
    1013
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    1619
    1720                $this->go_to( $user_domain );
    1821
     22                bp_core_new_nav_item( array(
     23                        'name'            => 'Foo Parent',
     24                        'slug'            => 'foo-parent',
     25                        'link'            => trailingslashit( $user_domain . 'foo-parent' ),
     26                        'screen_function' => 'foo_screen_function',
     27                        'position'        => 10,
     28                ) );
     29
    1930                bp_core_new_subnav_item( array(
    2031                        'name'            => 'Foo',
    2132                        'slug'            => 'foo',
    22                         'parent_url'      => trailingslashit( $user_domain . 'foo' ),
    23                         'parent_slug'     => 'foo',
     33                        'parent_url'      => trailingslashit( $user_domain . 'foo-parent' ),
     34                        'parent_slug'     => 'foo-parent',
    2435                        'screen_function' => 'foo_screen_function',
    2536                        'position'        => 10
    2637                ) );
    2738
    2839                $expected = array(
    2940                        'name'              => 'Foo',
    30                         'link'              => trailingslashit( $user_domain . 'foo/foo' ),
     41                        'link'              => trailingslashit( $user_domain . 'foo-parent/foo' ),
    3142                        'slug'              => 'foo',
    3243                        'css_id'            => 'foo',
    3344                        'position'          => 10,
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    3748                        'show_in_admin_bar' => false,
    3849                );
    3950
    40                 $this->assertSame( buddypress()->bp_options_nav['foo']['foo'], $expected );
     51                foreach ( $expected as $k => $v ) {
     52                        $this->assertSame( $v, buddypress()->bp_options_nav['foo-parent']['foo'][ $k ] );
     53                }
    4154
    4255                // Clean up
    4356                buddypress()->bp_options_nav = $bp_options_nav;
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    102115                $this->set_current_user( $old_current_user );
    103116        }
    104117
     118        /**
     119         * @expectedIncorrectUsage bp_nav
     120         */
    105121        public function test_link_provided() {
    106122                $bp_options_nav = buddypress()->bp_options_nav;
    107123
     124                bp_core_new_nav_item( array(
     125                        'name' => 'Foo',
     126                        'slug' => 'foo',
     127                        'screen_function' => 'foo',
     128                        'link' => 'https://buddypress.org/',
     129                ) );
     130
    108131                bp_core_new_subnav_item( array(
    109132                        'name' => 'bar',
    110133                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    119142                buddypress()->bp_options_nav = $bp_options_nav;
    120143        }
    121144
     145        /**
     146         * @expectedIncorrectUsage bp_nav
     147         */
    122148        public function test_link_built_from_parent_url_and_slug() {
    123149                $bp_options_nav = buddypress()->bp_options_nav;
    124150
     151                bp_core_new_nav_item( array(
     152                        'name' => 'Foo',
     153                        'slug' => 'foo',
     154                        'screen_function' => 'foo',
     155                        'link' => 'https://buddypress.org/',
     156                ) );
     157
    125158                bp_core_new_subnav_item( array(
    126159                        'name' => 'bar',
    127160                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    135168                buddypress()->bp_options_nav = $bp_options_nav;
    136169        }
    137170
     171        /**
     172         * @expectedIncorrectUsage bp_nav
     173         */
    138174        public function test_link_built_from_parent_url_and_slug_where_slug_is_default() {
    139175                $bp_nav = buddypress()->bp_nav;
    140176                $bp_options_nav = buddypress()->bp_options_nav;
    141177
    142                 // fake the parent
    143                 buddypress()->bp_nav = array(
    144                         'foo' => array(
    145                                 'default_subnav_slug' => 'bar',
    146                         ),
    147                 );
     178                bp_core_new_nav_item( array(
     179                        'name' => 'Foo',
     180                        'slug' => 'foo',
     181                        'screen_function' => 'foo',
     182                        'default_subnav_slug' => 'bar',
     183                ) );
    148184
    149185                bp_core_new_subnav_item( array(
    150186                        'name' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    161197                buddypress()->bp_options_nav = $bp_options_nav;
    162198        }
    163199
     200        /**
     201         * @expectedIncorrectUsage bp_nav
     202         */
    164203        public function test_should_trailingslash_link_when_link_is_autogenerated_using_slug() {
     204                bp_core_new_nav_item( array(
     205                        'name' => 'Foo',
     206                        'slug' => 'foo',
     207                        'screen_function' => 'foo',
     208                        'link' => 'https://buddypress.org/',
     209                ) );
     210
    165211                bp_core_new_subnav_item( array(
    166212                        'name' => 'bar',
    167213                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    174220                $this->assertSame( $expected, buddypress()->bp_options_nav['foo']['bar']['link'] );
    175221        }
    176222
     223        /**
     224         * @expectedIncorrectUsage bp_nav
     225         */
    177226        public function test_should_trailingslash_link_when_link_is_autogenerated_not_using_slug() {
    178227                bp_core_new_nav_item( array(
    179228                        'name' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    187236                        'name' => 'bar',
    188237                        'slug' => 'bar',
    189238                        'parent_slug' => 'foo-parent',
    190                         'parent_url' => bp_get_root_domain() . 'foo-parent/',
     239                        'parent_url' => bp_get_root_domain() . '/foo-parent/',
    191240                        'screen_function' => 'bar',
    192241                ) );
    193242
    194                 $expected = bp_get_root_domain() . 'foo-parent/';
     243                $expected = bp_get_root_domain() . '/foo-parent/';
    195244                $this->assertSame( $expected, buddypress()->bp_options_nav['foo-parent']['bar']['link'] );
    196245        }
    197246
    198247        /**
    199248         * @ticket BP6353
     249         * @expectedIncorrectUsage bp_nav
    200250         */
    201251        public function test_link_should_not_trailingslash_link_explicit_link() {
    202252                $link = 'http://example.com/foo/bar/blah/?action=edit&id=30';
    203253
     254                bp_core_new_nav_item( array(
     255                        'name' => 'Foo',
     256                        'slug' => 'foo',
     257                        'screen_function' => 'foo',
     258                        'link' => 'http://example.com/foo/',
     259                ) );
     260
    204261                bp_core_new_subnav_item( array(
    205262                        'name' => 'bar',
    206263                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    214271        }
    215272
    216273        public function test_should_return_false_if_site_admin_only_and_current_user_cannot_bp_moderate() {
     274                bp_core_new_nav_item( array(
     275                        'name' => 'Foo',
     276                        'slug' => 'foo',
     277                        'screen_function' => 'foo',
     278                ) );
     279
    217280                // Should already be set to a 0 user.
    218281                $this->assertFalse( bp_current_user_can( 'bp_moderate' ) );
    219282                $args = array(
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    228291                $this->assertFalse( bp_core_new_subnav_item( $args ) );
    229292        }
    230293
     294        /**
     295         * @expectedIncorrectUsage bp_nav
     296         */
    231297        public function test_css_id_should_fall_back_on_slug() {
     298                bp_core_new_nav_item( array(
     299                        'name' => 'Parent',
     300                        'slug' => 'parent',
     301                        'screen_function' => 'foo',
     302                ) );
     303
    232304                $args = array(
    233305                        'name' => 'Foo',
    234306                        'slug' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    241313                $this->assertSame( 'foo', buddypress()->bp_options_nav['parent']['foo']['css_id'] );
    242314        }
    243315
     316        /**
     317         * @expectedIncorrectUsage bp_nav
     318         */
    244319        public function test_css_id_should_be_respected() {
     320                bp_core_new_nav_item( array(
     321                        'name' => 'Parent',
     322                        'slug' => 'parent',
     323                        'screen_function' => 'foo',
     324                ) );
     325
    245326                $args = array(
    246327                        'name' => 'Foo',
    247328                        'slug' => 'foo',
  • tests/phpunit/testcases/groups/class-bp-group-extension.php

    diff --git tests/phpunit/testcases/groups/class-bp-group-extension.php tests/phpunit/testcases/groups/class-bp-group-extension.php
    index 55b12e5..e421c91 100644
    class BP_Tests_Group_Extension_TestCases extends BP_UnitTestCase { 
    217217
    218218        /**
    219219         * @group enable_nav_item
     220         * @expectedIncorrectUsage bp_nav
    220221         */
    221222        public function test_enable_nav_item_true() {
    222223                $old_options_nav = buddypress()->bp_options_nav;
    class BP_Tests_Group_Extension_TestCases extends BP_UnitTestCase { 
    239240
    240241        /**
    241242         * @group enable_nav_item
     243         * @expectedIncorrectUsage bp_nav
    242244         */
    243245        public function test_enable_nav_item_false() {
    244246                $old_options_nav = buddypress()->bp_options_nav;
    class BP_Tests_Group_Extension_TestCases extends BP_UnitTestCase { 
    261263
    262264        /**
    263265         * @group visibility
     266         * @expectedIncorrectUsage bp_nav
    264267         */
    265268        public function test_visibility_private() {
    266269                $old_options_nav = buddypress()->bp_options_nav;
    class BP_Tests_Group_Extension_TestCases extends BP_UnitTestCase { 
    298301
    299302        /**
    300303         * @group visibility
     304         * @expectedIncorrectUsage bp_nav
    301305         *
    302306         * visibility=public + status=private results in adding the item to
    303307         * the nav. However, BP_Groups_Component::setup_globals() bounces the
  • tests/phpunit/testcases/routing/anonymous.php

    diff --git tests/phpunit/testcases/routing/anonymous.php tests/phpunit/testcases/routing/anonymous.php
    index e83776f..a5234a8 100644
    class BP_Tests_Routing_Anonymous extends BP_UnitTestCase { 
    1010
    1111        function test_nav_menu() {
    1212                $this->go_to( '/' );
    13                 $this->assertEmpty( buddypress()->bp_nav );
     13                $nav = buddypress()->members->nav->get_item_nav();
     14                $this->assertEmpty( $nav );
    1415        }
    1516}
  • tests/phpunit/testcases/routing/core.php

    diff --git tests/phpunit/testcases/routing/core.php tests/phpunit/testcases/routing/core.php
    index 30f9a8e..fcb4a32 100644
    class BP_Tests_Routing_Core extends BP_UnitTestCase { 
    2222                $this->assertEmpty( bp_current_component() );
    2323        }
    2424
     25        /**
     26         * @expectedIncorrectUsage bp_nav
     27         */
    2528        function test_nav_menu() {
    2629                $this->go_to( '/' );
    2730                $this->assertArrayHasKey( 'activity', buddypress()->bp_nav );