Skip to:
Content

BuddyPress.org

Ticket #6534: 6534.diff

File 6534.diff, 108.6 KB (added by boonebgorges, 8 years ago)
  • src/bp-core/bp-core-buddybar.php

    diff --git a/src/bp-core/bp-core-buddybar.php b/src/bp-core/bp-core-buddybar.php
    index 9f1ffb0..98c23fb 100644
    a b  
    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 *
    18  * @since 1.1.0
     18 * @since 2.6.0
    1919 *
    2020 * @param array|string $args {
    2121 *     Array describing the new nav item.
    defined( 'ABSPATH' ) || exit; 
    3232 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    3333 *                                                item is clicked.
    3434 * }
     35 * @param string       $component                 The component the navigation is attached to. Defaults to 'members'.
    3536 * @return bool|null Returns false on failure.
    3637 */
    37 function bp_core_new_nav_item( $args = '' ) {
     38
     39function bp_core_add_nav_item( $args, $component = 'members' ) {
     40        if ( ! bp_is_active( $component ) ) {
     41                return;
     42        }
    3843
    3944        $defaults = array(
    4045                'name'                    => false, // Display name for the nav item.
    function bp_core_new_nav_item( $args = '' ) { 
    4954
    5055        $r = wp_parse_args( $args, $defaults );
    5156
    52         // First, add the nav item link to the bp_nav array.
    53         $created = bp_core_create_nav_link( $r );
     57        // Validate nav link data.
     58        $nav_item = bp_core_create_nav_link( $r, $component );
    5459
    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 ) {
     60        /*
     61         * To mimic legacy behavior, if bp_core_create_nav_link() returns false, we make
     62         * an early exit and don't attempt to register the screen function.
     63         */
     64        if ( false === $nav_item ) {
    5965                return false;
    6066        }
    6167
    6268        // Then, hook the screen function for the added nav item.
    63         $hooked = bp_core_register_nav_screen_function( $r );
     69        $hooked = bp_core_register_nav_screen_function( $nav_item );
    6470        if ( false === $hooked ){
    6571                return false;
    6672        }
    function bp_core_new_nav_item( $args = '' ) { 
    8187}
    8288
    8389/**
    84  * Add a link to the main BuddyPress navigation array.
     90 * Add a link to the main BuddyPress navigation.
    8591 *
    8692 * @since 2.4.0
     93 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
    8794 *
    8895 * @param array|string $args {
    8996 *     Array describing the new nav item.
    function bp_core_new_nav_item( $args = '' ) { 
    100107 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
    101108 *                                                item is clicked.
    102109 * }
    103  * @return bool|null Returns false on failure.
     110 * @param string $component Optional. Component that the nav belongs to.
     111 * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
    104112 */
    105 function bp_core_create_nav_link( $args = '' ) {
     113function bp_core_create_nav_link( $args = '', $component = 'members' ) {
    106114        $bp = buddypress();
    107115
    108116        $defaults = array(
    function bp_core_create_nav_link( $args = '' ) { 
    132140                $r['item_css_id'] = $r['slug'];
    133141        }
    134142
    135         $bp->bp_nav[$r['slug']] = array(
     143        $nav_item = array(
    136144                'name'                    => $r['name'],
    137145                'slug'                    => $r['slug'],
    138146                'link'                    => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ),
    function bp_core_create_nav_link( $args = '' ) { 
    143151                'default_subnav_slug'     => $r['default_subnav_slug']
    144152        );
    145153
     154        // Add the item to the nav.
     155        $retval = buddypress()->{$component}->nav->add_nav( $nav_item );
     156
    146157        /**
    147          * Fires after a link is added to the main BuddyPress navigation array.
     158         * Fires after a link is added to the main BuddyPress nav.
    148159         *
    149160         * @since 2.4.0
    150161         *
    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.
     162         * @param array  $r         Parsed arguments for the nav item.
     163         * @param array  $args      Originally passed in arguments for the nav item.
     164         * @param array  $defaults  Default arguments for a nav item.
     165         * @param string $component Component that the nav belongs to.
    154166         */
    155         do_action( 'bp_core_create_nav_link', $r, $args, $defaults );
     167        do_action( 'bp_core_create_nav_link', $r, $args, $defaults, $component );
     168
     169        return $retval;
    156170}
    157171
    158172/**
    function bp_core_new_nav_default( $args = '' ) { 
    290304
    291305        $r = wp_parse_args( $args, $defaults );
    292306
    293         if ( $function = $bp->bp_nav[$r['parent_slug']]['screen_function'] ) {
     307        // This is specific to Members - it's not available in Groups.
     308        $parent_nav = $bp->members->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     309
     310        if ( ! $parent_nav ) {
     311                return ;
     312        }
     313
     314        $parent_nav = reset( $parent_nav );
     315
     316        if ( ! empty( $parent_nav->screen_function ) ) {
    294317                // Remove our screen hook if screen function is callable.
    295                 if ( is_callable( $function ) ) {
    296                         remove_action( 'bp_screens', $function, 3 );
     318                if ( is_callable( $parent_nav->screen_function ) ) {
     319                        remove_action( 'bp_screens', $parent_nav->screen_function, 3 );
    297320                }
    298321        }
    299322
    300         $bp->bp_nav[$r['parent_slug']]['screen_function'] = &$r['screen_function'];
     323        // Edit the screen function for the parent nav
     324        $bp->members->nav->edit_nav( array(
     325                'screen_function'     => &$r['screen_function'],
     326                'default_subnav_slug' => $r['subnav_slug'],
     327        ), $parent_nav->slug );
    301328
    302         if ( bp_is_current_component( $r['parent_slug'] ) ) {
     329        if ( bp_is_current_component( $parent_nav->slug ) ) {
    303330
    304331                // The only way to tell whether to set the subnav is to peek at the unfiltered_uri
    305332                // Find the component.
    306                 $component_uri_key = array_search( $r['parent_slug'], $bp->unfiltered_uri );
     333                $component_uri_key = array_search( $parent_nav->slug, $bp->unfiltered_uri );
    307334
    308335                if ( false !== $component_uri_key ) {
    309336                        if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
    function bp_core_new_nav_default( $args = '' ) { 
    339366}
    340367
    341368/**
    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.
     369 * Add an item to secondary navigation of the specified component.
    346370 *
    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.
    381  *
    382  * @since 1.1.0
     371 * @since 2.6.0
    383372 *
    384373 * @param array|string $args {
    385374 *     Array describing the new subnav item.
    add_action( 'admin_head', 'bp_core_sort_nav_items' ); 
    403392 *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
    404393 *                                          Admin Bar menu for group admins. Default: false.
    405394 * }
     395 * @param string $component The component the navigation is attached to. Defaults to 'members'.
    406396 * @return bool|null Returns false on failure.
    407397 */
    408 function bp_core_new_subnav_item( $args = '' ) {
     398function bp_core_add_subnav_item( $args, $component = 'members' ) {
     399        if ( ! bp_is_active( $component ) ) {
     400                return;
     401        }
    409402
    410         // First, add the subnav item link to the bp_options_nav array.
    411         $created = bp_core_create_subnav_link( $args );
     403        // First, register the subnav item in the nav.
     404        $subnav_item = bp_core_create_subnav_link( $args, $component );
    412405
    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 ) {
     406        /*
     407         * To mimic legacy behavior, if bp_core_create_subnav_link() returns false, we make an
     408         * early exit and don't attempt to register the screen function.
     409         */
     410        if ( false === $subnav_item ) {
    417411                return false;
    418412        }
    419413
    420414        // Then, hook the screen function for the added subnav item.
    421         $hooked = bp_core_register_subnav_screen_function( $args );
     415        $hooked = bp_core_register_subnav_screen_function( $subnav_item, $component );
    422416        if ( false === $hooked ) {
    423417                return false;
    424418        }
    function bp_core_new_subnav_item( $args = '' ) { 
    428422 * Add a subnav link to the BuddyPress navigation.
    429423 *
    430424 * @since 2.4.0
     425 * @since 2.6.0 Introduced the `$component` parameter. Began returning a BP_Nav_Item object on success.
    431426 *
    432427 * @param array|string $args {
    433428 *     Array describing the new subnav item.
    function bp_core_new_subnav_item( $args = '' ) { 
    455450 *                                          the group's "Edit" Admin Bar menu for group admins.
    456451 *                                          Default: false.
    457452 * }
    458  * @return bool|null Returns false on failure.
     453 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     454 * @return bool|BP_Nav_Item Returns false on failure, new nav item on success.
    459455 */
    460 function bp_core_create_subnav_link( $args = '' ) {
     456function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
    461457        $bp = buddypress();
    462458
    463459        $r = wp_parse_args( $args, array(
    function bp_core_create_subnav_link( $args = '' ) { 
    483479        if ( empty( $r['link'] ) ) {
    484480                $r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] );
    485481
     482                $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     483
    486484                // 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'] );
     485                if ( $parent_nav ) {
     486                        $parent_nav_item = reset( $parent_nav );
     487                        if ( ! empty( $parent_nav_item->default_subnav_slug ) && $r['slug'] === $parent_nav_item->default_subnav_slug ) {
     488                                $r['link'] = trailingslashit( $r['parent_url'] );
     489                        }
    489490                }
    490491        }
    491492
    function bp_core_create_subnav_link( $args = '' ) { 
    502503                'name'              => $r['name'],
    503504                'link'              => $r['link'],
    504505                'slug'              => $r['slug'],
     506                'parent_slug'       => $r['parent_slug'],
    505507                'css_id'            => $r['item_css_id'],
    506508                'position'          => $r['position'],
    507509                'user_has_access'   => $r['user_has_access'],
    function bp_core_create_subnav_link( $args = '' ) { 
    510512                'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
    511513        );
    512514
    513         $bp->bp_options_nav[$r['parent_slug']][$r['slug']] = $subnav_item;
     515        return buddypress()->{$component}->nav->add_nav( $subnav_item );
    514516}
    515517
    516518/**
    517519 * Register a screen function, whether or not a related subnav link exists.
    518520 *
    519521 * @since 2.4.0
     522 * @since 2.6.0 Introduced the `$component` parameter.
    520523 *
    521524 * @param array|string $args {
    522525 *     Array describing the new subnav item.
    function bp_core_create_subnav_link( $args = '' ) { 
    541544 *                                       the group's "Edit" Admin Bar menu for group admins.
    542545 *                                       Default: false.
    543546 * }
     547 * @param string $component The component the navigation is attached to. Defaults to 'members'.
    544548 * @return bool|null Returns false on failure.
    545549 */
    546 function bp_core_register_subnav_screen_function( $args = '' ) {
     550function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
    547551        $bp = buddypress();
    548552
    549553        $r = wp_parse_args( $args, array(
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    555559                'screen_function'   => false, // The name of the function to run when clicked.
    556560        ) );
    557561
    558         /**
     562        /*
    559563         * Hook the screen function for the added subnav item. But this only needs to
    560564         * be done if this subnav item is the current view, and the user has access to the
    561565         * subnav item. We figure out whether we're currently viewing this subnav by
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    568572         *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
    569573         *       and this subnav item is the default for the parent item (which we check by
    570574         *       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.
     575         *       parent nav item in the component's primary nav). This condition only arises
     576         *       when viewing a user, since groups should always have an action set.
    573577         */
    574578
    575579        // If we *don't* meet condition (1), return.
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    577581                return;
    578582        }
    579583
     584        $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     585
    580586        // 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'] ) ) ) {
     587        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 ) ) {
    582588
    583589                // If this is for site admins only and the user is not one, don't create the subnav item.
    584590                if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
    585591                        return false;
    586592                }
    587593
    588                 $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r );
     594                $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r, $component );
    589595
    590596                // If redirect args have been returned, perform the redirect now.
    591597                if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    598604 * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary.
    599605 *
    600606 * @since 2.1.0
     607 * @since 2.6.0 Introduced the `$component` parameter.
    601608 *
    602  * @param array $subnav_item The subnav array added to bp_options_nav in `bp_core_new_subnav_item()`.
     609 * @param array  $subnav_item The subnav array added to the secondary navigation of
     610 *                            the component in bp_core_add_subnav_item().
     611 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    603612 * @return array
    604613 */
    605 function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) {
     614function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component = 'members' ) {
    606615        $retval = array(
    607616                'status' => '',
    608617        );
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    645654                        // redirect URL.
    646655                        } elseif ( bp_is_user() ) {
    647656
     657                                $parent_nav_default = $bp->{$component}->nav->get_primary( array( 'slug' => $bp->default_component ), false );
     658                                if ( $parent_nav_default ) {
     659                                        $parent_nav_default_item = reset( $parent_nav_default );
     660                                }
     661
    648662                                // Redirect to the displayed user's default
    649663                                // component, as long as that component is
    650664                                // publicly accessible.
    651                                 if ( bp_is_my_profile() || ! empty( $bp->bp_nav[ $bp->default_component ]['show_for_displayed_user'] ) ) {
     665                                if ( bp_is_my_profile() || ( isset( $parent_nav_default_item ) && $parent_nav_default_item->show_for_displayed_user ) ) {
    652666                                        $message     = __( 'You do not have access to this page.', 'buddypress' );
    653667                                        $redirect_to = bp_displayed_user_domain();
    654668
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    691705}
    692706
    693707/**
    694  * Sort all subnavigation arrays.
     708 * Check whether a given nav item has subnav items.
    695709 *
    696  * @since 1.1.0
     710 * @since 1.5.0
     711 * @since 2.6.0 Introduced the `$component` parameter.
    697712 *
    698  * @return bool|null Returns false on failure.
     713 * @param string $nav_item  The slug of the top-level nav item whose subnav items you're checking.
     714 *                          Default: the current component slug.
     715 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     716 * @return bool $has_subnav True if the nav item is found and has subnav items; false otherwise.
    699717 */
    700 function bp_core_sort_subnav_items() {
     718function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) {
    701719        $bp = buddypress();
    702720
    703         if ( empty( $bp->bp_options_nav ) || !is_array( $bp->bp_options_nav ) )
     721        if ( ! isset( $bp->{$component}->nav ) ) {
    704722                return false;
     723        }
    705724
    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']] ) );
     725        if ( ! $nav_item ) {
     726                $nav_item = bp_current_component();
    718727
    719                                 $temp[$subnav_item['position']] = $subnav_item;
    720                         }
     728                if ( bp_is_group() ) {
     729                        $nav_item = bp_current_item();
    721730                }
    722                 ksort( $temp );
    723                 $bp->bp_options_nav[$parent_slug] = &$temp;
    724                 unset( $temp );
    725731        }
    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();
    744732
    745         $has_subnav = isset( $bp->bp_options_nav[$nav_item] ) && count( $bp->bp_options_nav[$nav_item] ) > 0;
     733        $has_subnav = (bool) $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $nav_item ), false );
    746734
    747735        /**
    748736         * Filters whether or not a given nav item has subnav items.
    function bp_nav_item_has_subnav( $nav_item = '' ) { 
    756744}
    757745
    758746/**
    759  * Remove a nav item from the navigation array.
     747 * Deletes an item from the primary navigation of the specified component.
    760748 *
    761  * @since 1.0.0
     749 * @since 2.6.0
    762750 *
    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.
     751 * @param string $slug      The slug of the primary navigation item.
     752 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     753 * @return bool Returns false on failure, True on success.
    765754 */
    766 function bp_core_remove_nav_item( $parent_id ) {
     755function bp_core_delete_nav_item( $slug, $component = 'members' ) {
    767756        $bp = buddypress();
    768757
    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                 }
     758        if ( ! isset( $bp->{$component}->nav ) ) {
     759                return false;
    774760        }
    775761
    776         if ( empty( $bp->bp_nav[ $parent_id ] ) )
     762        $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
     763
     764        if ( ! is_array( $screen_functions ) ) {
    777765                return false;
     766        }
    778767
    779         if ( $function = $bp->bp_nav[$parent_id]['screen_function'] ) {
     768        foreach ( $screen_functions as $screen_function ) {
    780769                // Remove our screen hook if screen function is callable.
    781                 if ( is_callable( $function ) ) {
    782                         remove_action( 'bp_screens', $function, 3 );
     770                if ( is_callable( $screen_function ) ) {
     771                        remove_action( 'bp_screens', $screen_function, 3 );
    783772                }
    784773        }
    785774
    786         unset( $bp->bp_nav[$parent_id] );
     775        return true;
    787776}
    788777
    789778/**
    790  * Remove a subnav item from the navigation array.
     779 * Deletes an item from the secondary navigation of the specified component.
    791780 *
    792  * @since 1.0.0
     781 * @since 2.6.0
    793782 *
    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.
     783 * @param string $slug        The slug of the secondary item to be removed.
     784 * @param string $parent_slug The slug of the primary navigation item.
     785 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
     786 * @return bool Returns false on failure, True on success.
    796787 */
    797 function bp_core_remove_subnav_item( $parent_id, $slug ) {
     788function bp_core_delete_subnav_item( $slug, $parent_slug, $component = 'members' ) {
    798789        $bp = buddypress();
    799790
    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;
     791        if ( ! isset( $bp->{$component}->nav ) ) {
     792                return false;
     793        }
     794
     795        $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
    803796
    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                 }
     797        if ( ! is_array( $screen_functions ) ) {
     798                return false;
    809799        }
    810800
    811         unset( $bp->bp_options_nav[$parent_id][$slug] );
     801        $screen_function = reset( $screen_functions );
     802
     803        // Remove our screen hook if screen function is callable.
     804        if ( is_callable( $screen_function ) ) {
     805                remove_action( 'bp_screens', $screen_function, 3 );
     806        }
    812807
    813         if ( isset( $bp->bp_options_nav[$parent_id] ) && !count( $bp->bp_options_nav[$parent_id] ) )
    814                 unset($bp->bp_options_nav[$parent_id]);
     808        return true;
    815809}
    816810
    817811/**
    818812 * Clear all subnav items from a specific nav item.
    819813 *
    820814 * @since 1.0.0
     815 * @since 2.6.0 Introduced the `$component` parameter.
    821816 *
    822817 * @param string $parent_slug The slug of the parent navigation item.
     818 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    823819 */
    824 function bp_core_reset_subnav_items( $parent_slug ) {
     820function bp_core_reset_subnav_items( $parent_slug, $component = 'members' ) {
    825821        $bp = buddypress();
    826822
    827         unset( $bp->bp_options_nav[$parent_slug] );
     823        if ( ! isset( $bp->{$component}->nav ) ) {
     824                return;
     825        }
     826
     827        $subnav_items = $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $parent_slug ), false );
     828
     829        if ( ! $subnav_items ) {
     830                return;
     831        }
     832
     833        foreach( $subnav_items as $subnav_item ) {
     834                $bp->{$component}->nav->delete_nav( $subnav_item->slug, $parent_slug );
     835        }
    828836}
    829837
    830838
  • src/bp-core/bp-core-catchuri.php

    diff --git a/src/bp-core/bp-core-catchuri.php b/src/bp-core/bp-core-catchuri.php
    index e78f67b..6b35960 100644
    a b add_action( 'login_form_bpnoaccess', 'bp_core_no_access_wp_login_error' ); 
    684684 *
    685685 * @see BP_Members_Component::setup_globals() where
    686686 *      $bp->canonical_stack['base_url'] and ['component'] may be set.
    687  * @see bp_core_new_nav_item() where $bp->canonical_stack['action'] may be set.
     687 * @see bp_core_add_nav_item() where $bp->canonical_stack['action'] may be set.
    688688 * @uses bp_get_canonical_url()
    689689 * @uses bp_get_requested_url()
    690690 */
  • src/bp-core/bp-core-classes.php

    diff --git a/src/bp-core/bp-core-classes.php b/src/bp-core/bp-core-classes.php
    index bebf4ed..9d2d377 100644
    a b 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 a/src/bp-core/bp-core-functions.php b/src/bp-core/bp-core-functions.php
    index 702d0dd..a489fd4 100644
    a b 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 a/src/bp-core/bp-core-template.php b/src/bp-core/bp-core-template.php
    index 1f2c5e9..abfb275 100644
    a b 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 a/src/bp-core/classes/class-bp-component.php b/src/bp-core/classes/class-bp-component.php
    index 8a53680..5fdab1d 100644
    a b class BP_Component { 
    473473         * Set up component navigation.
    474474         *
    475475         * @since 1.5.0
     476         * @since 2.6.0 Use bp_core_add_nav_item() instead of bp_core_new_nav_item() (deprecated)
     477         *                              Use bp_core_add_subnav_item() instead of bp_core_new_subnav_item() (deprecated)
    476478         *
    477          * @see bp_core_new_nav_item() For a description of the $main_nav
     479         * @see bp_core_add_nav_item() For a description of the $main_nav
    478480         *      parameter formatting.
    479          * @see bp_core_new_subnav_item() For a description of how each item
     481         * @see bp_core_add_subnav_item() For a description of how each item
    480482         *      in the $sub_nav parameter array should be formatted.
    481483         *
    482          * @param array $main_nav Optional. Passed directly to bp_core_new_nav_item().
     484         * @param array $main_nav Optional. Passed directly to bp_core_add_nav_item().
    483485         *                        See that function for a description.
    484486         * @param array $sub_nav  Optional. Multidimensional array, each item in
    485          *                        which is passed to bp_core_new_subnav_item(). See that
     487         *                        which is passed to bp_core_add_subnav_item(). See that
    486488         *                        function for a description.
    487489         */
    488490        public function setup_nav( $main_nav = array(), $sub_nav = array() ) {
    489491
    490492                // No sub nav items without a main nav item.
    491493                if ( !empty( $main_nav ) ) {
    492                         bp_core_new_nav_item( $main_nav );
     494                        bp_core_add_nav_item( $main_nav, 'members' );
    493495
    494496                        // Sub nav items are not required.
    495497                        if ( !empty( $sub_nav ) ) {
    496498                                foreach( (array) $sub_nav as $nav ) {
    497                                         bp_core_new_subnav_item( $nav );
     499                                        bp_core_add_subnav_item( $nav, 'members' );
    498500                                }
    499501                        }
    500502                }
  • new file src/bp-core/classes/class-bp-core-bp-nav-backcompat.php

    diff --git a/src/bp-core/classes/class-bp-core-bp-nav-backcompat.php b/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 a/src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php b/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 a/src/bp-core/classes/class-bp-core-nav-item.php b/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 a/src/bp-core/classes/class-bp-core-nav.php b/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 a/src/bp-core/classes/class-bp-core.php b/src/bp-core/classes/class-bp-core.php
    index 3cdfc0e..e6cc35b 100644
    a b 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 a/src/bp-core/deprecated/2.6.php b/src/bp-core/deprecated/2.6.php
    index acc5e23..758ea90 100644
    a b function bp_core_print_generation_time() { 
    2121
    2222        <?php
    2323}
     24
     25/**
     26 * Add an item to the main BuddyPress navigation array.
     27 *
     28 * @since 1.1.0
     29 * @deprecated 2.6.0
     30 *
     31 * @param array|string $args {
     32 *     Array describing the new nav item.
     33 *     @type string      $name                    Display name for the nav item.
     34 *     @type string      $slug                    Unique URL slug for the nav item.
     35 *     @type bool|string $item_css_id             Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
     36 *     @type bool        $show_for_displayed_user Optional. Whether the nav item should be visible when viewing a
     37 *                                                member profile other than your own. Default: true.
     38 *     @type bool        $site_admin_only         Optional. Whether the nav item should be visible only to site admins
     39 *                                                (those with the 'bp_moderate' cap). Default: false.
     40 *     @type int         $position                Optional. Numerical index specifying where the item should appear in
     41 *                                                the nav array. Default: 99.
     42 *     @type callable    $screen_function         The callback function that will run when the nav item is clicked.
     43 *     @type bool|string $default_subnav_slug     Optional. The slug of the default subnav item to select when the nav
     44 *                                                item is clicked.
     45 * }
     46 * @return bool|null Returns false on failure.
     47 */
     48function bp_core_new_nav_item( $args = '' ) {
     49        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_add_nav_item' );
     50        return bp_core_add_nav_item( $args );
     51}
     52
     53/**
     54 * Sort the navigation menu items.
     55 *
     56 * The sorting is split into a separate function because it can only happen
     57 * after all plugins have had a chance to register their navigation items.
     58 *
     59 * @since 1.0.0
     60 * @deprecated 2.6.0
     61 *
     62 * @return bool|null Returns false on failure.
     63 */
     64function bp_core_sort_nav_items() {
     65        _deprecated_function( __FUNCTION__, '2.6' );
     66}
     67
     68/**
     69 * Add a subnav item to the BuddyPress navigation.
     70 *
     71 * @since 1.1.0
     72 * @deprecated 2.6.0
     73 *
     74 * @param array|string $args {
     75 *     Array describing the new subnav item.
     76 *     @type string      $name              Display name for the subnav item.
     77 *     @type string      $slug              Unique URL slug for the subnav item.
     78 *     @type string      $parent_slug       Slug of the top-level nav item under which the new subnav item should
     79 *                                          be added.
     80 *     @type string      $parent_url        URL of the parent nav item.
     81 *     @type bool|string $item_css_id       Optional. 'id' attribute for the nav item. Default: the value of `$slug`.
     82 *     @type bool        $user_has_access   Optional. True if the logged-in user has access to the subnav item,
     83 *                                          otherwise false. Can be set dynamically when registering the subnav;
     84 *                                          eg, use `bp_is_my_profile()` to restrict access to profile owners only.
     85 *                                          Default: true.
     86 *     @type bool        $site_admin_only   Optional. Whether the nav item should be visible only to site admins
     87 *                                          (those with the 'bp_moderate' cap). Default: false.
     88 *     @type int         $position          Optional. Numerical index specifying where the item should appear in the
     89 *                                          subnav array. Default: 90.
     90 *     @type callable    $screen_function   The callback function that will run when the nav item is clicked.
     91 *     @type string      $link              Optional. The URL that the subnav item should point to. Defaults to a value
     92 *                                          generated from the `$parent_url` + `$slug`.
     93 *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
     94 *                                          Admin Bar menu for group admins. Default: false.
     95 * }
     96 * @return bool|null Returns false on failure.
     97 */
     98function bp_core_new_subnav_item( $args = '' ) {
     99        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_add_subnav_item' );
     100
     101        // Attempt to determine whether this is intended to be a group navigation item.
     102        $component = 'members';
     103        if ( bp_is_active( 'groups' ) && bp_is_group() && isset( $args['parent_slug'] ) ) {
     104                /*
     105                 * Assume that this item is intended to belong to the current group if:
     106                 * a) the 'parent_slug' is the same as the slug of the current group, or
     107                 * b) the 'parent_slug' starts with the slug of the current group, and the members nav doesn't have
     108                 *    a primary item with that slug
     109                 */
     110                $group_slug = bp_get_current_group_slug();
     111                if (
     112                        $group_slug === $args['parent_slug'] ||
     113                        ( 0 === strpos( $args['parent_slug'], $group_slug ) && ! buddypress()->members->nav->get_primary( array( 'slug' => $args['parent_slug'] ), false ) )
     114                ) {
     115                        $component = 'groups';
     116                }
     117        }
     118
     119        return bp_core_add_subnav_item( $args, $component );
     120}
     121
     122/**
     123 * Sort all subnavigation arrays.
     124 *
     125 * @since 1.1.0
     126 * @deprecated 2.6.0
     127 *
     128 * @return bool|null Returns false on failure.
     129 */
     130function bp_core_sort_subnav_items() {
     131        _deprecated_function( __FUNCTION__, '2.6' );
     132}
     133
     134/**
     135 * Remove a nav item from the navigation array.
     136 *
     137 * @since 1.0.0
     138 * @deprecated 2.6.0
     139 *
     140 * @param int $parent_id The slug of the parent navigation item.
     141 * @return bool Returns false on failure, ie if the nav item can't be found.
     142 */
     143function bp_core_remove_nav_item( $parent_id ) {
     144        $bp = buddypress();
     145
     146        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_nav_item' );
     147
     148        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     149
     150                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     151                        return bp_core_delete_nav_item( $parent_id, 'groups' );
     152                }
     153        }
     154
     155        return bp_core_delete_nav_item( $parent_id );
     156}
     157
     158/**
     159 * Remove a subnav item from the navigation array.
     160 *
     161 * @since 1.0.0
     162 * @deprecated 2.6.0
     163 *
     164 * @param string $parent_id The slug of the parent navigation item.
     165 * @param string $slug      The slug of the subnav item to be removed.
     166 */
     167function bp_core_remove_subnav_item( $parent_id, $slug ) {
     168        $bp = buddypress();
     169
     170        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_subnav_item' );
     171
     172        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     173
     174                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     175                        return bp_core_delete_subnav_item( $slug, $parent_id, 'groups' );
     176                }
     177        }
     178
     179        return bp_core_delete_subnav_item( $slug, $parent_id );
     180}
  • src/bp-groups/bp-groups-adminbar.php

    diff --git a/src/bp-groups/bp-groups-adminbar.php b/src/bp-groups/bp-groups-adminbar.php
    index f27f74e..6cef4b5 100644
    a b 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 a/src/bp-groups/classes/class-bp-group-extension.php b/src/bp-groups/classes/class-bp-group-extension.php
    index 5709b0b..7209401 100644
    a b 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_add_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 a/src/bp-groups/classes/class-bp-groups-component.php b/src/bp-groups/classes/class-bp-groups-component.php
    index 355ab8c..e5f89da 100644
    a b 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_add_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_add_subnav_item( $nav, 'groups' );
     682                        }
    679683                }
    680684
    681685                if ( isset( $this->current_group->user_has_access ) ) {
  • src/bp-loader.php

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

    diff --git a/tests/phpunit/testcases/core/nav/bpCoreMaybeHookNewSubnavScreenFunction.php b/tests/phpunit/testcases/core/nav/bpCoreMaybeHookNewSubnavScreenFunction.php
    index 2ebc74c..d0b10e1 100644
    a b 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_add_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_add_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 a/tests/phpunit/testcases/core/nav/bpCoreNewNavItem.php b/tests/phpunit/testcases/core/nav/bpCoreNewNavItem.php
    index b6f6439..db9c69e 100644
    a b  
    55 */
    66class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase {
    77
     8        /**
     9         * @expectedDeprecated bp_core_new_nav_item
     10         * @expectedIncorrectUsage bp_nav
     11         */
    812        public function test_user_nav() {
    913                $bp_nav = buddypress()->bp_nav;
    1014
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    3337                        'default_subnav_slug'     => 'foo-sub'
    3438                );
    3539
    36                 $this->assertSame( buddypress()->bp_nav['foo'], $expected );
     40                foreach ( $expected as $k => $v ) {
     41                        $this->assertEquals( $v, buddypress()->bp_nav['foo'][ $k ] );
     42                }
    3743
    3844                // Clean up
    3945                buddypress()->bp_nav = $bp_nav;
    4046                $this->set_current_user( $old_current_user );
    4147        }
    4248
     49        /**
     50         * @expectedIncorrectUsage bp_nav
     51         */
    4352        public function test_group_nav() {
    4453                $bp_nav = buddypress()->bp_nav;
    4554
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    6170                $this->set_current_user( $old_current_user );
    6271        }
    6372
     73        /**
     74         * @expectedDeprecated bp_core_new_nav_item
     75         */
    6476        public function test_should_return_false_if_name_is_not_provided() {
    6577                $args = array(
    6678                        'slug' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    6981                $this->assertFalse( bp_core_new_nav_item( $args ) );
    7082        }
    7183
     84        /**
     85         * @expectedDeprecated bp_core_new_nav_item
     86         */
    7287        public function test_should_return_false_if_slug_is_not_provided() {
    7388                $args = array(
    7489                        'name' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    7792                $this->assertFalse( bp_core_new_nav_item( $args ) );
    7893        }
    7994
     95        /**
     96         * @expectedDeprecated bp_core_new_nav_item
     97         */
    8098        public function test_should_return_false_if_site_admin_only_and_current_user_cannot_bp_moderate() {
    8199                // Should already be set to a 0 user.
    82100                $this->assertFalse( bp_current_user_can( 'bp_moderate' ) );
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    89107                $this->assertFalse( bp_core_new_nav_item( $args ) );
    90108        }
    91109
     110        /**
     111         * @expectedDeprecated bp_core_new_nav_item
     112         * @expectedIncorrectUsage bp_nav
     113         */
    92114        public function test_css_id_should_fall_back_on_slug() {
    93115                $args = array(
    94116                        'name' => 'Foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    99121                $this->assertSame( 'foo', buddypress()->bp_nav['foo']['css_id'] );
    100122        }
    101123
     124        /**
     125         * @expectedDeprecated bp_core_new_nav_item
     126         * @expectedIncorrectUsage bp_nav
     127         */
    102128        public function test_css_id_should_be_respected() {
    103129                $args = array(
    104130                        'name' => 'Foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    110136                $this->assertSame( 'bar', buddypress()->bp_nav['foo']['css_id'] );
    111137        }
    112138
     139        /**
     140         * @expectedDeprecated bp_core_new_nav_item
     141         */
    113142        public function test_show_for_displayed_user_false_should_force_function_to_return_false_when_bp_user_has_access_is_also_false() {
    114143                $args = array(
    115144                        'name' => 'Foo',
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    124153                $this->assertFalse( $retval );
    125154        }
    126155
     156        /**
     157         * @expectedIncorrectUsage bp_nav
     158         */
    127159        public function test_existence_of_access_protected_user_nav() {
    128160                $bp_nav = buddypress()->bp_nav;
    129161
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    145177                        'default_subnav_slug'     => 'general'
    146178                );
    147179
    148                 $this->assertSame( buddypress()->bp_nav['settings'], $expected );
     180                foreach ( $expected as $k => $v ) {
     181                        $this->assertEquals( $v, buddypress()->bp_nav['settings'][ $k ] );
     182                }
    149183
    150184                // Clean up
    151185                buddypress()->bp_nav = $bp_nav;
    152186                $this->set_current_user( $old_current_user );
    153187        }
    154188
     189        /**
     190         * @expectedIncorrectUsage bp_nav
     191         * @expectedDeprecated bp_core_new_nav_item
     192         */
    155193        public function test_creation_of_access_protected_user_nav() {
    156194                // The nav item must be added to bp_nav, even if the current user
    157195                // can't visit that nav item.
    class BP_Tests_Core_Nav_BpCoreNewNavItem extends BP_UnitTestCase { 
    184222                        'default_subnav_slug'     => 'woof-one'
    185223                );
    186224
    187                 $this->assertSame( buddypress()->bp_nav['woof'], $expected );
     225                foreach ( $expected as $k => $v ) {
     226                        $this->assertEquals( $v, buddypress()->bp_nav['woof'][ $k ] );
     227                }
    188228
    189229                // Clean up
    190230                buddypress()->bp_nav = $bp_nav;
  • tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php

    diff --git a/tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php b/tests/phpunit/testcases/core/nav/bpCoreNewSubnavItem.php
    index cf07a2f..09faa55 100644
    a b  
    55 */
    66class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase {
    77
     8        /**
     9         * @expectedDeprecated bp_core_new_nav_item
     10         * @expectedDeprecated bp_core_new_subnav_item
     11         * @expectedIncorrectUsage bp_nav
     12         */
    813        public function test_user_subnav() {
    914                $bp_options_nav = buddypress()->bp_options_nav;
    1015
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    1621
    1722                $this->go_to( $user_domain );
    1823
     24                bp_core_new_nav_item( array(
     25                        'name'            => 'Foo Parent',
     26                        'slug'            => 'foo-parent',
     27                        'link'            => trailingslashit( $user_domain . 'foo-parent' ),
     28                        'screen_function' => 'foo_screen_function',
     29                        'position'        => 10,
     30                ) );
     31
    1932                bp_core_new_subnav_item( array(
    2033                        'name'            => 'Foo',
    2134                        'slug'            => 'foo',
    22                         'parent_url'      => trailingslashit( $user_domain . 'foo' ),
    23                         'parent_slug'     => 'foo',
     35                        'parent_url'      => trailingslashit( $user_domain . 'foo-parent' ),
     36                        'parent_slug'     => 'foo-parent',
    2437                        'screen_function' => 'foo_screen_function',
    2538                        'position'        => 10
    2639                ) );
    2740
    2841                $expected = array(
    2942                        'name'              => 'Foo',
    30                         'link'              => trailingslashit( $user_domain . 'foo/foo' ),
     43                        'link'              => trailingslashit( $user_domain . 'foo-parent/foo' ),
    3144                        'slug'              => 'foo',
    3245                        'css_id'            => 'foo',
    3346                        'position'          => 10,
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    3750                        'show_in_admin_bar' => false,
    3851                );
    3952
    40                 $this->assertSame( buddypress()->bp_options_nav['foo']['foo'], $expected );
     53                foreach ( $expected as $k => $v ) {
     54                        $this->assertSame( $v, buddypress()->bp_options_nav['foo-parent']['foo'][ $k ] );
     55                }
    4156
    4257                // Clean up
    4358                buddypress()->bp_options_nav = $bp_options_nav;
    4459                $this->set_current_user( $old_current_user );
    4560        }
    4661
     62        /**
     63         * @expectedDeprecated bp_core_new_subnav_item
     64         */
    4765        public function test_required_params() {
    4866                // 'name'
    4967                $this->assertFalse( bp_core_new_subnav_item( array(
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    86104                ) ) );
    87105        }
    88106
     107        /**
     108         * @expectedDeprecated bp_core_new_subnav_item
     109         */
    89110        public function test_site_admin_only() {
    90111                $old_current_user = get_current_user_id();
    91112                $this->set_current_user( 0 );
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    102123                $this->set_current_user( $old_current_user );
    103124        }
    104125
     126        /**
     127         * @expectedDeprecated bp_core_new_subnav_item
     128         * @expectedIncorrectUsage bp_nav
     129         */
    105130        public function test_link_provided() {
    106131                $bp_options_nav = buddypress()->bp_options_nav;
    107132
     133                bp_core_add_nav_item( array(
     134                        'name' => 'Foo',
     135                        'slug' => 'foo',
     136                        'screen_function' => 'foo',
     137                        'link' => 'https://buddypress.org/',
     138                ) );
     139
    108140                bp_core_new_subnav_item( array(
    109141                        'name' => 'bar',
    110142                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    119151                buddypress()->bp_options_nav = $bp_options_nav;
    120152        }
    121153
     154        /**
     155         * @expectedDeprecated bp_core_new_subnav_item
     156         * @expectedIncorrectUsage bp_nav
     157         */
    122158        public function test_link_built_from_parent_url_and_slug() {
    123159                $bp_options_nav = buddypress()->bp_options_nav;
    124160
     161                bp_core_add_nav_item( array(
     162                        'name' => 'Foo',
     163                        'slug' => 'foo',
     164                        'screen_function' => 'foo',
     165                        'link' => 'https://buddypress.org/',
     166                ) );
     167
    125168                bp_core_new_subnav_item( array(
    126169                        'name' => 'bar',
    127170                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    135178                buddypress()->bp_options_nav = $bp_options_nav;
    136179        }
    137180
     181        /**
     182         * @expectedDeprecated bp_core_new_subnav_item
     183         * @expectedIncorrectUsage bp_nav
     184         */
    138185        public function test_link_built_from_parent_url_and_slug_where_slug_is_default() {
    139186                $bp_nav = buddypress()->bp_nav;
    140187                $bp_options_nav = buddypress()->bp_options_nav;
    141188
    142                 // fake the parent
    143                 buddypress()->bp_nav = array(
    144                         'foo' => array(
    145                                 'default_subnav_slug' => 'bar',
    146                         ),
    147                 );
     189                bp_core_add_nav_item( array(
     190                        'name' => 'Foo',
     191                        'slug' => 'foo',
     192                        'screen_function' => 'foo',
     193                        'default_subnav_slug' => 'bar',
     194                ) );
    148195
    149196                bp_core_new_subnav_item( array(
    150197                        'name' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    161208                buddypress()->bp_options_nav = $bp_options_nav;
    162209        }
    163210
     211        /**
     212         * @expectedDeprecated bp_core_new_subnav_item
     213         * @expectedIncorrectUsage bp_nav
     214         */
    164215        public function test_should_trailingslash_link_when_link_is_autogenerated_using_slug() {
     216                bp_core_add_nav_item( array(
     217                        'name' => 'Foo',
     218                        'slug' => 'foo',
     219                        'screen_function' => 'foo',
     220                        'link' => 'https://buddypress.org/',
     221                ) );
     222
    165223                bp_core_new_subnav_item( array(
    166224                        'name' => 'bar',
    167225                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    174232                $this->assertSame( $expected, buddypress()->bp_options_nav['foo']['bar']['link'] );
    175233        }
    176234
     235        /**
     236         * @expectedDeprecated bp_core_new_nav_item
     237         * @expectedDeprecated bp_core_new_subnav_item
     238         * @expectedIncorrectUsage bp_nav
     239         */
    177240        public function test_should_trailingslash_link_when_link_is_autogenerated_not_using_slug() {
    178241                bp_core_new_nav_item( array(
    179242                        'name' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    187250                        'name' => 'bar',
    188251                        'slug' => 'bar',
    189252                        'parent_slug' => 'foo-parent',
    190                         'parent_url' => bp_get_root_domain() . 'foo-parent/',
     253                        'parent_url' => bp_get_root_domain() . '/foo-parent/',
    191254                        'screen_function' => 'bar',
    192255                ) );
    193256
    194                 $expected = bp_get_root_domain() . 'foo-parent/';
     257                $expected = bp_get_root_domain() . '/foo-parent/';
    195258                $this->assertSame( $expected, buddypress()->bp_options_nav['foo-parent']['bar']['link'] );
    196259        }
    197260
    198261        /**
    199262         * @ticket BP6353
     263         * @expectedDeprecated bp_core_new_subnav_item
     264         * @expectedIncorrectUsage bp_nav
    200265         */
    201266        public function test_link_should_not_trailingslash_link_explicit_link() {
    202267                $link = 'http://example.com/foo/bar/blah/?action=edit&id=30';
    203268
     269                bp_core_add_nav_item( array(
     270                        'name' => 'Foo',
     271                        'slug' => 'foo',
     272                        'screen_function' => 'foo',
     273                        'link' => 'http://example.com/foo/',
     274                ) );
     275
    204276                bp_core_new_subnav_item( array(
    205277                        'name' => 'bar',
    206278                        'slug' => 'bar',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    213285                $this->assertSame( $link, buddypress()->bp_options_nav['foo']['bar']['link'] );
    214286        }
    215287
     288        /**
     289         * @expectedDeprecated bp_core_new_subnav_item
     290         */
    216291        public function test_should_return_false_if_site_admin_only_and_current_user_cannot_bp_moderate() {
     292                bp_core_add_nav_item( array(
     293                        'name' => 'Foo',
     294                        'slug' => 'foo',
     295                        'screen_function' => 'foo',
     296                ) );
     297
    217298                // Should already be set to a 0 user.
    218299                $this->assertFalse( bp_current_user_can( 'bp_moderate' ) );
    219300                $args = array(
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    228309                $this->assertFalse( bp_core_new_subnav_item( $args ) );
    229310        }
    230311
     312        /**
     313         * @expectedDeprecated bp_core_new_subnav_item
     314         * @expectedIncorrectUsage bp_nav
     315         */
    231316        public function test_css_id_should_fall_back_on_slug() {
     317                bp_core_add_nav_item( array(
     318                        'name' => 'Parent',
     319                        'slug' => 'parent',
     320                        'screen_function' => 'foo',
     321                ) );
     322
    232323                $args = array(
    233324                        'name' => 'Foo',
    234325                        'slug' => 'foo',
    class BP_Tests_Core_Nav_BpCoreNewSubnavItem extends BP_UnitTestCase { 
    241332                $this->assertSame( 'foo', buddypress()->bp_options_nav['parent']['foo']['css_id'] );
    242333        }
    243334
     335        /**
     336         * @expectedDeprecated bp_core_new_subnav_item
     337         * @expectedIncorrectUsage bp_nav
     338         */
    244339        public function test_css_id_should_be_respected() {
     340                bp_core_add_nav_item( array(
     341                        'name' => 'Parent',
     342                        'slug' => 'parent',
     343                        'screen_function' => 'foo',
     344                ) );
     345
    245346                $args = array(
    246347                        'name' => 'Foo',
    247348                        'slug' => 'foo',
  • tests/phpunit/testcases/groups/class-bp-group-extension.php

    diff --git a/tests/phpunit/testcases/groups/class-bp-group-extension.php b/tests/phpunit/testcases/groups/class-bp-group-extension.php
    index 55b12e5..e421c91 100644
    a b 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 a/tests/phpunit/testcases/routing/anonymous.php b/tests/phpunit/testcases/routing/anonymous.php
    index e83776f..a5234a8 100644
    a b 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 a/tests/phpunit/testcases/routing/core.php b/tests/phpunit/testcases/routing/core.php
    index 30f9a8e..fcb4a32 100644
    a b 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 );