Skip to:
Content

BuddyPress.org

Ticket #6534: 6534.04.patch

File 6534.04.patch, 72.3 KB (added by imath, 9 years ago)
  • src/bp-core/bp-core-buddybar.php

    diff --git src/bp-core/bp-core-buddybar.php src/bp-core/bp-core-buddybar.php
    index 9f1ffb0..e0a8ae4 100644
     
    1313defined( 'ABSPATH' ) || exit;
    1414
    1515/**
    16  * Add an item to the main BuddyPress navigation array.
     16 * Add an item to the primary navigation of the specified component.
    1717 *
    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        // First, add the nav item link to the primary nav for the component.
     58        $nav_item = bp_core_create_nav_link( $r );
     59
     60        /**
     61         * Fires after a link is added to the main BuddyPress navigation array.
     62         *
     63         * @since 2.4.0
     64         *
     65         * @param array $r        Parsed arguments for the nav item.
     66         * @param array $args     Originally passed in arguments for the nav item.
     67         * @param array $defaults Default arguments for a nav item.
     68         */
     69        do_action( 'bp_core_create_nav_link', $r, $args, $defaults );
    5470
    5571        // To mimic the existing behavior, if bp_core_create_nav_link()
    5672        // returns false, we make an early exit and don't attempt to register
    5773        // the screen function.
    58         if ( false === $created ) {
     74        if ( false === $nav_item ) {
    5975                return false;
    6076        }
    6177
    6278        // Then, hook the screen function for the added nav item.
    63         $hooked = bp_core_register_nav_screen_function( $r );
     79        $hooked = bp_core_register_nav_screen_function( $nav_item );
    6480        if ( false === $hooked ){
    6581                return false;
    6682        }
    6783
     84        // Add the item to the nav
     85        buddypress()->{$component}->nav->add_nav( $nav_item );
     86
    6887        /**
    6988         * Fires after adding an item to the main BuddyPress navigation array.
    7089         * Note that, when possible, the more specific action hooks
    function bp_core_create_nav_link( $args = '' ) { 
    132151                $r['item_css_id'] = $r['slug'];
    133152        }
    134153
    135         $bp->bp_nav[$r['slug']] = array(
     154        return array(
    136155                'name'                    => $r['name'],
    137156                'slug'                    => $r['slug'],
    138157                'link'                    => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ),
    function bp_core_create_nav_link( $args = '' ) { 
    142161                'screen_function'         => &$r['screen_function'],
    143162                'default_subnav_slug'     => $r['default_subnav_slug']
    144163        );
    145 
    146         /**
    147          * Fires after a link is added to the main BuddyPress navigation array.
    148          *
    149          * @since 2.4.0
    150          *
    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.
    154          */
    155         do_action( 'bp_core_create_nav_link', $r, $args, $defaults );
    156164}
    157165
    158166/**
    function bp_core_new_nav_default( $args = '' ) { 
    290298
    291299        $r = wp_parse_args( $args, $defaults );
    292300
    293         if ( $function = $bp->bp_nav[$r['parent_slug']]['screen_function'] ) {
     301        // This is specific to Members, it's not available in Groups.
     302        $parent_nav = $bp->members->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     303
     304        if ( ! $parent_nav ) {
     305                return ;
     306        }
     307
     308        $parent_nav = reset( $parent_nav );
     309
     310        if ( ! empty( $parent_nav->screen_function ) ) {
    294311                // Remove our screen hook if screen function is callable.
    295                 if ( is_callable( $function ) ) {
    296                         remove_action( 'bp_screens', $function, 3 );
     312                if ( is_callable( $parent_nav->screen_function ) ) {
     313                        remove_action( 'bp_screens', $parent_nav->screen_function, 3 );
    297314                }
    298315        }
    299316
    300         $bp->bp_nav[$r['parent_slug']]['screen_function'] = &$r['screen_function'];
     317        // Edit the screen function for the parent nav
     318        $bp->members->nav->edit_nav( array(
     319                'screen_function'     => &$r['screen_function'],
     320                'default_subnav_slug' => $r['subnav_slug'],
     321        ), $parent_nav->slug );
    301322
    302         if ( bp_is_current_component( $r['parent_slug'] ) ) {
     323        if ( bp_is_current_component( $parent_nav->slug ) ) {
    303324
    304325                // The only way to tell whether to set the subnav is to peek at the unfiltered_uri
    305326                // Find the component.
    306                 $component_uri_key = array_search( $r['parent_slug'], $bp->unfiltered_uri );
     327                $component_uri_key = array_search( $parent_nav->slug, $bp->unfiltered_uri );
    307328
    308329                if ( false !== $component_uri_key ) {
    309330                        if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) {
    function bp_core_new_nav_default( $args = '' ) { 
    339360}
    340361
    341362/**
    342  * Sort the navigation menu items.
    343  *
    344  * The sorting is split into a separate function because it can only happen
    345  * after all plugins have had a chance to register their navigation items.
    346  *
    347  * @since 1.0.0
    348  *
    349  * @return bool|null Returns false on failure.
    350  */
    351 function bp_core_sort_nav_items() {
    352         $bp = buddypress();
    353 
    354         if ( empty( $bp->bp_nav ) || ! is_array( $bp->bp_nav ) ) {
    355                 return false;
    356         }
    357 
    358         $temp = array();
    359 
    360         foreach ( (array) $bp->bp_nav as $slug => $nav_item ) {
    361                 if ( empty( $temp[$nav_item['position']] ) ) {
    362                         $temp[$nav_item['position']] = $nav_item;
    363                 } else {
    364                         // Increase numbers here to fit new items in.
    365                         do {
    366                                 $nav_item['position']++;
    367                         } while ( ! empty( $temp[$nav_item['position']] ) );
    368 
    369                         $temp[$nav_item['position']] = $nav_item;
    370                 }
    371         }
    372 
    373         ksort( $temp );
    374         $bp->bp_nav = &$temp;
    375 }
    376 add_action( 'wp_head',    'bp_core_sort_nav_items' );
    377 add_action( 'admin_head', 'bp_core_sort_nav_items' );
    378 
    379 /**
    380  * Add a subnav item to the BuddyPress navigation.
     363 * Add an item to secondary navigation of the specified component.
    381364 *
    382  * @since 1.1.0
     365 * @since 2.6.0
    383366 *
    384367 * @param array|string $args {
    385368 *     Array describing the new subnav item.
    add_action( 'admin_head', 'bp_core_sort_nav_items' ); 
    403386 *     @type bool        $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit"
    404387 *                                          Admin Bar menu for group admins. Default: false.
    405388 * }
     389 * @param  string       $component          The component the navigation is attached to. Defaults to 'members'.
    406390 * @return bool|null Returns false on failure.
    407391 */
    408 function bp_core_new_subnav_item( $args = '' ) {
     392function bp_core_add_subnav_item( $args, $component = 'members' ) {
     393        if ( ! bp_is_active( $component ) ) {
     394                return;
     395        }
    409396
    410397        // First, add the subnav item link to the bp_options_nav array.
    411         $created = bp_core_create_subnav_link( $args );
     398        $subnav_item = bp_core_create_subnav_link( $args, $component );
    412399
    413400        // To mimic the existing behavior, if bp_core_create_subnav_link()
    414401        // returns false, we make an early exit and don't attempt to register
    415402        // the screen function.
    416         if ( false === $created ) {
     403        if ( false === $subnav_item ) {
    417404                return false;
    418405        }
    419406
    420407        // Then, hook the screen function for the added subnav item.
    421         $hooked = bp_core_register_subnav_screen_function( $args );
     408        $hooked = bp_core_register_subnav_screen_function( $subnav_item, $component );
    422409        if ( false === $hooked ) {
    423410                return false;
    424411        }
    function bp_core_new_subnav_item( $args = '' ) { 
    428415 * Add a subnav link to the BuddyPress navigation.
    429416 *
    430417 * @since 2.4.0
     418 * @since 2.6.0 Adds the $component parameter.
    431419 *
    432420 * @param array|string $args {
    433421 *     Array describing the new subnav item.
    function bp_core_new_subnav_item( $args = '' ) { 
    455443 *                                          the group's "Edit" Admin Bar menu for group admins.
    456444 *                                          Default: false.
    457445 * }
     446 * @param  string       $component          The component the navigation is attached to. Defaults to 'members'.
    458447 * @return bool|null Returns false on failure.
    459448 */
    460 function bp_core_create_subnav_link( $args = '' ) {
     449function bp_core_create_subnav_link( $args = '', $component = 'members' ) {
    461450        $bp = buddypress();
    462451
    463452        $r = wp_parse_args( $args, array(
    function bp_core_create_subnav_link( $args = '' ) { 
    483472        if ( empty( $r['link'] ) ) {
    484473                $r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] );
    485474
     475                $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     476
    486477                // 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'] ) {
     478                if ( ! empty( $parent_nav->default_subnav_slug ) && $r['slug'] === $parent_nav->default_subnav_slug ) {
    488479                        $r['link'] = trailingslashit( $r['parent_url'] );
    489480                }
    490481        }
    function bp_core_create_subnav_link( $args = '' ) { 
    502493                'name'              => $r['name'],
    503494                'link'              => $r['link'],
    504495                'slug'              => $r['slug'],
     496                'parent_slug'       => $r['parent_slug'],
    505497                'css_id'            => $r['item_css_id'],
    506498                'position'          => $r['position'],
    507499                'user_has_access'   => $r['user_has_access'],
    function bp_core_create_subnav_link( $args = '' ) { 
    510502                'show_in_admin_bar' => (bool) $r['show_in_admin_bar'],
    511503        );
    512504
    513         $bp->bp_options_nav[$r['parent_slug']][$r['slug']] = $subnav_item;
     505        buddypress()->{$component}->nav->add_nav( $subnav_item );
     506
     507        return $subnav_item;
    514508}
    515509
    516510/**
    517511 * Register a screen function, whether or not a related subnav link exists.
    518512 *
    519513 * @since 2.4.0
     514 * @since 2.6.0 Adds the $component parameter.
    520515 *
    521516 * @param array|string $args {
    522517 *     Array describing the new subnav item.
    function bp_core_create_subnav_link( $args = '' ) { 
    541536 *                                       the group's "Edit" Admin Bar menu for group admins.
    542537 *                                       Default: false.
    543538 * }
     539 * @param  string       $component          The component the navigation is attached to. Defaults to 'members'.
    544540 * @return bool|null Returns false on failure.
    545541 */
    546 function bp_core_register_subnav_screen_function( $args = '' ) {
     542function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) {
    547543        $bp = buddypress();
    548544
    549545        $r = wp_parse_args( $args, array(
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    568564         *       (b) there is no current_action (ie, this is the default subnav for the parent nav)
    569565         *       and this subnav item is the default for the parent item (which we check by
    570566         *       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
     567         *       parent nav item in the component's primary nav). This condition only arises when viewing a
    572568         *       user, since groups should always have an action set.
    573569         */
    574570
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    577573                return;
    578574        }
    579575
     576        $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false );
     577
    580578        // 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'] ) ) ) {
     579        if ( ( bp_current_action() && bp_is_current_action( $r['slug'] ) ) || ( bp_is_user() && ! bp_current_action() && ( $r['screen_function'] == $parent_nav->screen_function ) ) ) {
    582580
    583581                // If this is for site admins only and the user is not one, don't create the subnav item.
    584582                if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) {
    585583                        return false;
    586584                }
    587585
    588                 $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r );
     586                $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r, $component );
    589587
    590588                // If redirect args have been returned, perform the redirect now.
    591589                if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) {
    function bp_core_register_subnav_screen_function( $args = '' ) { 
    598596 * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary.
    599597 *
    600598 * @since 2.1.0
     599 * @since 2.6.0 Adds the $component parameter.
    601600 *
    602  * @param array $subnav_item The subnav array added to bp_options_nav in `bp_core_new_subnav_item()`.
     601 * @param array  $subnav_item The subnav array added to the secondary navigation of the component in `bp_core_add_subnav_item()`.
     602 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    603603 * @return array
    604604 */
    605 function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) {
     605function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component = 'members' ) {
    606606        $retval = array(
    607607                'status' => '',
    608608        );
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    645645                        // redirect URL.
    646646                        } elseif ( bp_is_user() ) {
    647647
     648                                $parent_nav_default = $bp->{$component}->nav->get_primary( array( 'slug' => $bp->default_component ), false );
     649
    648650                                // Redirect to the displayed user's default
    649651                                // component, as long as that component is
    650652                                // publicly accessible.
    651                                 if ( bp_is_my_profile() || ! empty( $bp->bp_nav[ $bp->default_component ]['show_for_displayed_user'] ) ) {
     653                                if ( bp_is_my_profile() || ! empty( $parent_nav_default->show_for_displayed_user ) ) {
    652654                                        $message     = __( 'You do not have access to this page.', 'buddypress' );
    653655                                        $redirect_to = bp_displayed_user_domain();
    654656
    function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 
    691693}
    692694
    693695/**
    694  * Sort all subnavigation arrays.
     696 * Check whether a given nav item has subnav items.
    695697 *
    696  * @since 1.1.0
     698 * @since 1.5.0
     699 * @since 2.6.0 Adds the $component parameter.
    697700 *
    698  * @return bool|null Returns false on failure.
     701 * @param string $nav_item  The slug of the top-level nav item whose subnav items you're checking.
     702 *                          Default: the current component slug.
     703 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     704 * @return bool $has_subnav True if the nav item is found and has subnav items; false otherwise.
    699705 */
    700 function bp_core_sort_subnav_items() {
     706function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) {
    701707        $bp = buddypress();
    702708
    703         if ( empty( $bp->bp_options_nav ) || !is_array( $bp->bp_options_nav ) )
     709        if ( ! isset( $bp->{$component}->nav ) ) {
    704710                return false;
     711        }
    705712
    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']] ) );
     713        if ( ! $nav_item ) {
     714                $nav_item = bp_current_component();
    718715
    719                                 $temp[$subnav_item['position']] = $subnav_item;
    720                         }
     716                if ( bp_is_group() ) {
     717                        $nav_item = bp_current_item();
    721718                }
    722                 ksort( $temp );
    723                 $bp->bp_options_nav[$parent_slug] = &$temp;
    724                 unset( $temp );
    725719        }
    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();
    744720
    745         $has_subnav = isset( $bp->bp_options_nav[$nav_item] ) && count( $bp->bp_options_nav[$nav_item] ) > 0;
     721        $has_subnav = (bool) $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $nav_item ), false );
    746722
    747723        /**
    748724         * Filters whether or not a given nav item has subnav items.
    function bp_nav_item_has_subnav( $nav_item = '' ) { 
    756732}
    757733
    758734/**
    759  * Remove a nav item from the navigation array.
     735 * Deletes an item from the primary navigation of the specified component.
    760736 *
    761  * @since 1.0.0
     737 * @since 2.6.0
    762738 *
    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.
     739 * @param string $slug      The slug of the primary navigation item.
     740 * @param string $component The component the navigation is attached to. Defaults to 'members'.
     741 * @return bool Returns false on failure, True on success.
    765742 */
    766 function bp_core_remove_nav_item( $parent_id ) {
     743function bp_core_delete_nav_item( $slug, $component = 'members' ) {
    767744        $bp = buddypress();
    768745
    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                 }
     746        if ( ! isset( $bp->{$component}->nav ) ) {
     747                return false;
    774748        }
    775749
    776         if ( empty( $bp->bp_nav[ $parent_id ] ) )
     750        $screen_functions = $bp->{$component}->nav->delete_nav( $slug );
     751
     752        if ( ! is_array( $screen_functions ) ) {
    777753                return false;
     754        }
    778755
    779         if ( $function = $bp->bp_nav[$parent_id]['screen_function'] ) {
     756        foreach ( $screen_functions as $screen_function ) {
    780757                // Remove our screen hook if screen function is callable.
    781                 if ( is_callable( $function ) ) {
    782                         remove_action( 'bp_screens', $function, 3 );
     758                if ( is_callable( $screen_function ) ) {
     759                        remove_action( 'bp_screens', $screen_function, 3 );
    783760                }
    784761        }
    785762
    786         unset( $bp->bp_nav[$parent_id] );
     763        return true;
    787764}
    788765
    789766/**
    790  * Remove a subnav item from the navigation array.
     767 * Deletes an item from the secondary navigation of the specified component.
    791768 *
    792  * @since 1.0.0
     769 * @since 2.6.0
    793770 *
    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.
     771 * @param string $slug        The slug of the secondary item to be removed.
     772 * @param string $parent_slug The slug of the primary navigation item.
     773 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
     774 * @return bool Returns false on failure, True on success.
    796775 */
    797 function bp_core_remove_subnav_item( $parent_id, $slug ) {
     776function bp_core_delete_subnav_item( $slug, $parent_slug, $component = 'members' ) {
    798777        $bp = buddypress();
    799778
    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;
     779        if ( ! isset( $bp->{$component}->nav ) ) {
     780                return false;
     781        }
    803782
    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                 }
     783        $screen_functions = $bp->{$component}->nav->delete_nav( $slug, $parent_slug );
     784
     785        if ( ! is_array( $screen_functions ) ) {
     786                return false;
    809787        }
    810788
    811         unset( $bp->bp_options_nav[$parent_id][$slug] );
     789        $screen_function = reset( $screen_functions );
    812790
    813         if ( isset( $bp->bp_options_nav[$parent_id] ) && !count( $bp->bp_options_nav[$parent_id] ) )
    814                 unset($bp->bp_options_nav[$parent_id]);
     791        // Remove our screen hook if screen function is callable.
     792        if ( is_callable( $screen_function ) ) {
     793                remove_action( 'bp_screens', $screen_function, 3 );
     794        }
     795
     796        return true;
    815797}
    816798
    817799/**
    818800 * Clear all subnav items from a specific nav item.
    819801 *
    820802 * @since 1.0.0
     803 * @since 2.6.0 Adds the $component parameter.
    821804 *
    822805 * @param string $parent_slug The slug of the parent navigation item.
     806 * @param string $component   The component the navigation is attached to. Defaults to 'members'.
    823807 */
    824 function bp_core_reset_subnav_items( $parent_slug ) {
     808function bp_core_reset_subnav_items( $parent_slug, $component = 'members' ) {
    825809        $bp = buddypress();
    826810
    827         unset( $bp->bp_options_nav[$parent_slug] );
     811        if ( ! isset( $bp->{$component}->nav ) ) {
     812                return;
     813        }
     814
     815        $subnav_items = $bp->{$component}->nav->get_secondary( array( 'parent_slug' => $parent_slug ), false );
     816
     817        if ( ! $subnav_items ) {
     818                return;
     819        }
     820
     821        foreach( $subnav_items as $subnav_item ) {
     822                $bp->{$component}->nav->delete_nav( $subnav_item->slug, $parent_slug );
     823        }
    828824}
    829825
    830826
  • src/bp-core/bp-core-catchuri.php

    diff --git src/bp-core/bp-core-catchuri.php src/bp-core/bp-core-catchuri.php
    index e78f67b..6b35960 100644
    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 src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php
    index bebf4ed..bb886d0 100644
    require dirname( __FILE__ ) . '/classes/class-bp-email-recipient.php'; 
    3030require dirname( __FILE__ ) . '/classes/class-bp-email.php';
    3131require dirname( __FILE__ ) . '/classes/class-bp-email-delivery.php';
    3232require dirname( __FILE__ ) . '/classes/class-bp-phpmailer.php';
     33require dirname( __FILE__ ) . '/classes/class-bp-core-nav.php';
     34require dirname( __FILE__ ) . '/classes/class-bp-core-backcompat-nav.php';
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index 702d0dd..ea81687 100644
    function bp_nav_menu_get_loggedin_pages() { 
    24432443                return buddypress()->wp_nav_menu_items->loggedin;
    24442444        }
    24452445
    2446         // Pull up a list of items registered in BP's top-level nav array.
    2447         $bp_menu_items = buddypress()->bp_nav;
    2448 
    2449         // Alphabetize.
    2450         $bp_menu_items = bp_alpha_sort_by_key( $bp_menu_items, 'name' );
     2446        // Pull up a list of items registered in BP's primary nav for the member.
     2447        $bp_menu_items = buddypress()->members->nav->get_primary();
    24512448
    24522449        // Some BP nav menu items will not be represented in bp_nav, because
    24532450        // they are not real BP components. We add them manually here.
    2454         $bp_menu_items[] = array(
     2451        $bp_menu_items[] = (object) array(
    24552452                'name' => __( 'Log Out', 'buddypress' ),
    24562453                'slug' => 'logout',
    24572454                'link' => wp_logout_url(),
    function bp_nav_menu_get_loggedin_pages() { 
    24672464        foreach ( $bp_menu_items as $bp_item ) {
    24682465
    24692466                // Remove <span>number</span>.
    2470                 $item_name = _bp_strip_spans_from_title( $bp_item['name'] );
     2467                $item_name = _bp_strip_spans_from_title( $bp_item->name );
    24712468
    2472                 $page_args[ $bp_item['slug'] ] = (object) array(
     2469                $page_args[ $bp_item->slug ] = (object) array(
    24732470                        'ID'             => -1,
    24742471                        'post_title'     => $item_name,
    24752472                        'post_author'    => 0,
    24762473                        'post_date'      => 0,
    2477                         'post_excerpt'   => $bp_item['slug'],
     2474                        'post_excerpt'   => $bp_item->slug,
    24782475                        'post_type'      => 'page',
    24792476                        'post_status'    => 'publish',
    24802477                        'comment_status' => 'closed',
    2481                         'guid'           => $bp_item['link']
     2478                        'guid'           => $bp_item->link
    24822479                );
    24832480        }
    24842481
    function bp_nav_menu_get_loggedout_pages() { 
    25752572 * @since 1.9.0
    25762573 *
    25772574 * @param string $slug The slug of the nav item: login, register, or one of the
    2578  *                     slugs from buddypress()->bp_nav.
     2575 *                     slugs from the members navigation.
    25792576 * @return string $nav_item_url The URL generated for the current user.
    25802577 */
    25812578function bp_nav_menu_get_item_url( $slug ) {
  • src/bp-core/bp-core-template.php

    diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
    index 1f2c5e9..48fd117 100644
    defined( 'ABSPATH' ) || exit; 
    1313/**
    1414 * Output the "options nav", the secondary-level single item navigation menu.
    1515 *
    16  * Uses the $bp->bp_options_nav global to render out the sub navigation for the
     16 * Uses the component's nav global to render out the sub navigation for the
    1717 * current component. Each component adds to its sub navigation array within
    1818 * its own setup_nav() function.
    1919 *
    function bp_get_options_nav( $parent_slug = '' ) { 
    4040        $component_index = !empty( $bp->displayed_user ) ? bp_current_component() : bp_get_root_slug( bp_current_component() );
    4141        $selected_item   = bp_current_action();
    4242
     43        /**
     44         * Use the members Nav
     45         */
    4346        if ( ! bp_is_single_item() ) {
    44                 if ( !isset( $bp->bp_options_nav[$component_index] ) || count( $bp->bp_options_nav[$component_index] ) < 1 ) {
     47                // Set the parent slug if not provided
     48                if ( empty( $parent_slug ) ) {
     49                        $parent_slug = $component_index;
     50                }
     51
     52                $secondary_nav_items = $bp->members->nav->get_secondary( array( 'parent_slug' => $parent_slug ) );
     53
     54                if ( ! $secondary_nav_items ) {
    4555                        return false;
    46                 } else {
    47                         $the_index = $component_index;
    4856                }
     57
     58        /**
     59         * Try to use the component's Nav for the single item.
     60         */
    4961        } else {
    5062                $current_item = bp_current_item();
     63                $single_item_component = bp_current_component();
    5164
     65                // Adjust the selected nav item for the current single item if needed
    5266                if ( ! empty( $parent_slug ) ) {
    5367                        $current_item  = $parent_slug;
    5468                        $selected_item = bp_action_variable( 0 );
    5569                }
    5670
    57                 if ( !isset( $bp->bp_options_nav[$current_item] ) || count( $bp->bp_options_nav[$current_item] ) < 1 ) {
    58                         return false;
     71                // The nav is not defined by the parent component, try to look in the members one
     72                if ( ! isset( $bp->{$single_item_component}->nav ) ) {
     73                        $secondary_nav_items = $bp->members->nav->get_secondary( array( 'parent_slug' => $current_item ) );
    5974                } else {
    60                         $the_index = $current_item;
     75                        $secondary_nav_items = $bp->{$single_item_component}->nav->get_secondary( array( 'parent_slug' => $current_item ) );
     76                }
     77
     78                if ( ! $secondary_nav_items ) {
     79                        return false;
    6180                }
    6281        }
    6382
    6483        // 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'] ) ) {
     84        foreach ( $secondary_nav_items as $subnav_item ) {
     85                if ( empty( $subnav_item->user_has_access ) ) {
    6786                        continue;
    6887                }
    6988
    7089                // 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 ) {
     90                if ( $subnav_item->slug === $selected_item ) {
    7291                        $selected = ' class="current selected"';
    7392                } else {
    7493                        $selected = '';
    function bp_get_options_nav( $parent_slug = '' ) { 
    88107                 * @param array  $subnav_item   Submenu array item being displayed.
    89108                 * @param string $selected_item Current action.
    90109                 */
    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 );
     110                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 );
    92111        }
    93112}
    94113
    function bp_get_title_parts( $seplocation = 'right' ) { 
    30103029                // Set empty subnav name.
    30113030                $component_subnav_name = '';
    30123031
     3032                if ( ! empty( $bp->members->nav ) ) {
     3033                        $primary_nav_item = $bp->members->nav->get_primary( array( 'slug' => $component_id ), false );
     3034                        $primary_nav_item = reset( $primary_nav_item );
     3035                }
     3036
    30133037                // 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'] );
     3038                if ( ! empty( $primary_nav_item->name ) ) {
     3039                        $component_name = _bp_strip_spans_from_title( $primary_nav_item->name );
    30163040
    30173041                // Fall back on the component ID.
    30183042                } elseif ( ! empty( $bp->{$component_id}->id ) ) {
    30193043                        $component_name = ucwords( $bp->{$component_id}->id );
    30203044                }
    30213045
    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' );
     3046                if ( ! empty( $bp->members->nav ) ) {
     3047                        $secondary_nav_item = $bp->members->nav->get_secondary( array(
     3048                                'parent_slug' => $component_id,
     3049                                'slug'        => bp_current_action()
     3050                        ), false );
    30253051
    3026                         if ( ! empty( $component_subnav_name ) ) {
    3027                                 $component_subnav_name = array_shift( $component_subnav_name );
     3052                        if ( $secondary_nav_item ) {
     3053                                $secondary_nav_item = reset( $secondary_nav_item );
    30283054                        }
    30293055                }
    30303056
     3057                // Append action name if we're on a member component sub-page.
     3058                if ( ! empty( $secondary_nav_item->name ) && ! empty( $bp->canonical_stack['action'] ) ) {
     3059                        $component_subnav_name = $secondary_nav_item->name;
     3060                }
     3061
    30313062                // If on the user profile's landing page, just use the fullname.
    30323063                if ( bp_is_current_component( $bp->default_component ) && ( bp_get_requested_url() === bp_displayed_user_domain() ) ) {
    30333064                        $bp_title_parts[] = $displayed_user_name;
    function bp_get_title_parts( $seplocation = 'right' ) { 
    30453076                        }
    30463077                }
    30473078
    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.
     3079        // A single item from a component other than members.
    30543080        } 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'] );
     3081                $component_id = bp_current_component();
     3082
     3083                if ( ! empty( $bp->{$component_id}->nav ) ) {
     3084                        $secondary_nav_item = $bp->{$component_id}->nav->get_secondary( array(
     3085                                'parent_slug' => bp_current_item(),
     3086                                'slug'        => bp_current_action()
     3087                        ), false );
     3088
     3089                        if ( $secondary_nav_item ) {
     3090                                $secondary_nav_item = reset( $secondary_nav_item );
     3091                        }
     3092                }
     3093
     3094                $single_item_subnav = '';
     3095
     3096                if ( ! empty( $secondary_nav_item->name ) ) {
     3097                        $single_item_subnav = $secondary_nav_item->name;
     3098                }
     3099
     3100                $bp_title_parts = array( $bp->bp_options_title, $single_item_subnav );
    30563101
    30573102        // An index or directory.
    30583103        } elseif ( bp_is_directory() ) {
    function _bp_nav_menu_sort( $a, $b ) { 
    34283473 * Get the items registered in the primary and secondary BuddyPress navigation menus.
    34293474 *
    34303475 * @since 1.7.0
     3476 * @since 2.6.0 Add the component parameter to be able to get the menu items for any single item
    34313477 *
    34323478 * @return array A multidimensional array of all navigation items.
    34333479 */
    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                 }
     3480function bp_get_nav_menu_items( $component = 'members' ) {
     3481        $bp    = buddypress();
     3482        $menus = array();
    34443483
    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                         }
    3470 
    3471                         $menus[] = $menu;
    3472                 }
     3484        if ( ! isset( $bp->{$component}->nav ) ) {
     3485                return $menus;
    34733486        }
    34743487
    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 
     3488        // Get the item nav and build the menus
     3489        foreach ( $bp->{$component}->nav->get_item_nav() as $nav_menu ) {
    34873490                // 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'] );
     3491                $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 );
    34893492
    34903493                // Add this menu.
    34913494                $menu         = new stdClass;
    34923495                $menu->class  = array( 'menu-parent' );
    3493                 $menu->css_id = $nav['css_id'];
    3494                 $menu->link   = $link;
    3495                 $menu->name   = $nav['name'];
     3496                $menu->css_id = $nav_menu->css_id;
     3497                $menu->link   = $nav_menu->link;
     3498                $menu->name   = $nav_menu->name;
    34963499                $menu->parent = 0;
    34973500
    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';
     3501                if ( ! empty( $nav_menu->children ) ) {
     3502                        $submenus = array();
     3503
     3504                        foreach( $nav_menu->children as $sub_menu ) {
     3505                                $submenu = new stdClass;
     3506                                $submenu->class  = array( 'menu-child' );
     3507                                $submenu->css_id = $sub_menu->css_id;
     3508                                $submenu->link   = $sub_menu->link;
     3509                                $submenu->name   = $sub_menu->name;
     3510                                $submenu->parent = $nav_menu->slug;
     3511
     3512                                // If we're viewing this item's screen, record that we need to mark its parent menu to be selected.
     3513                                if ( $sub_menu->slug == bp_current_action() ) {
     3514                                        $menu->class[]    = 'current-menu-parent';
     3515                                        $submenu->class[] = 'current-menu-item';
     3516                                }
     3517
     3518                                $submenus[] = $submenu;
     3519                        }
    35013520                }
    35023521
    35033522                $menus[] = $menu;
     3523
     3524                if ( ! empty( $submenus ) ) {
     3525                        $menus = array_merge( $menus, $submenus );
     3526                }
    35043527        }
    35053528
    35063529        /**
  • src/bp-core/classes/class-bp-component.php

    diff --git src/bp-core/classes/class-bp-component.php src/bp-core/classes/class-bp-component.php
    index 8a53680..5fdab1d 100644
    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                }
  • src/bp-core/classes/class-bp-core-backcompat-nav.php

    diff --git src/bp-core/classes/class-bp-core-backcompat-nav.php src/bp-core/classes/class-bp-core-backcompat-nav.php
    index e69de29..784dae3 100644
     
     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 BackCompat Nav.
     15 *
     16 * This class is used to provide Backward compatibility
     17 * in case people are directly accessing the buddypress()->bp_nav global
     18 *
     19 * @since 2.6.0
     20 */
     21class BP_Core_BackCompat_Nav implements ArrayAccess {
     22        public $backcompat_nav;
     23
     24        public function __construct( $backcompat_nav = array() ) {
     25                foreach ( $backcompat_nav as $key => $value ) {
     26                        $this->backcompat_nav[ $key ] = $value;
     27                }
     28        }
     29
     30        public function offsetSet( $offset, $value ) {
     31                $bp = buddypress();
     32
     33                if ( is_array( $value ) ) {
     34                        $value = new self( $value );
     35                }
     36
     37                if ( $offset !== null ) {
     38                        // Set the backcompat_nav
     39                        $this->backcompat_nav[ $offset ] = $value;
     40
     41                        _doing_it_wrong(
     42                                'buddypress()->bp_nav',
     43                                __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     44                                '2.6.0'
     45                        );
     46
     47                        // This should never be the case!
     48                        if ( ! isset( $bp->members->nav ) ) {
     49                                return;
     50                        }
     51
     52                        // The primary nav already exists and the user is trying to edit it.
     53                        if ( ! empty( $this->backcompat_nav['slug'] ) ) {
     54                                $primary_nav = $bp->members->nav->get_primary( array( 'slug' => $this->backcompat_nav['slug'] ), false );
     55
     56                                // Primary nav item exists, so edit it!
     57                                if ( ! empty( $primary_nav ) ) {
     58                                        $primary_nav = reset( $primary_nav );
     59                                        $bp->members->nav->edit_nav( (array) $this->backcompat_nav, $primary_nav->slug );
     60                                }
     61
     62                        // Check if it's a complete new nav item and create it if needed.
     63                        } else if ( ! empty( $value->backcompat_nav ) && isset( $value['slug'] ) ) {
     64                                // Add the new nav
     65                                $bp->members->nav->add_nav( $value->backcompat_nav );
     66                        }
     67                }
     68        }
     69
     70        public function get_nav( $offset ) {
     71                $bp = buddypress();
     72
     73                if ( isset( $bp->members->nav ) ) {
     74                        $primary_nav = $bp->members->nav->get_primary( array( 'slug' => $offset ), false );
     75                        $nav         = array();
     76
     77                        if ( empty( $primary_nav ) ) {
     78                                return $nav;
     79                        }
     80
     81                        foreach( $primary_nav as $item ) {
     82                                $nav[ $item->slug ] = (array) $item;
     83                        }
     84
     85                        return $nav;
     86                }
     87        }
     88
     89        public function offsetGet( $offset ) {
     90                if ( ! isset( $this->backcompat_nav[ $offset ] ) ) {
     91                        $this->backcompat_nav[ $offset ] = new self;
     92
     93                        if ( empty( $this->backcompat_nav[ $offset ]->backcompat_nav ) ) {
     94                                $nav = $this->get_nav( $offset );
     95
     96                                if ( ! empty( $nav[ $offset ] ) ) {
     97                                        $this->backcompat_nav[ $offset ] = new self( $nav[ $offset ] );
     98                                }
     99                        }
     100                }
     101
     102                _doing_it_wrong(
     103                        'buddypress()->bp_nav',
     104                        __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     105                        '2.6.0'
     106                );
     107
     108                return $this->backcompat_nav[ $offset ];
     109        }
     110
     111        public function offsetExists( $offset ) {
     112                return isset( $this->backcompat_nav[ $offset ] );
     113        }
     114
     115        public function offsetUnset( $offset ) {
     116                unset( $this->backcompat_nav );
     117        }
     118}
     119
     120/**
     121 * BuddyPress BackCompat Options Nav.
     122 *
     123 * This class is used to provide Backward compatibility
     124 * in case people are directly accessing the buddypress()->bp_options_nav global
     125 *
     126 * @since 2.6.0
     127 */
     128class BP_Core_BackCompat_Options_Nav extends BP_Core_BackCompat_Nav {
     129
     130        public function get_parent_slug( $subnav, $offset ) {
     131                $parent_slug = false;
     132
     133                if ( ! is_array( $subnav ) || empty( $subnav['slug'] ) ) {
     134                        return $parent_slug;
     135                }
     136
     137                if ( ! empty( $subnav['parent_slug'] ) ) {
     138                        $parent_slug = $subnav['parent_slug'];
     139
     140                /**
     141                 * Unfortunately the parent slug is not part of the args
     142                 * when a bp_options_nav item is first created, So we need to parse the url to find it.
     143                 */
     144                } else {
     145                        $s = str_replace( array( bp_get_members_slug(), $offset ), '', parse_url( $subnav['link'], PHP_URL_PATH ) );
     146                        $s = explode( '/', trim( $s, '/' ) );
     147
     148                        if ( ! empty( $s[1] ) ) {
     149                                $parent_slug = $s[1];
     150                        }
     151                }
     152
     153                return $parent_slug;
     154        }
     155
     156        public function get_component( $parent_slug ) {
     157                $component = 'members';
     158
     159                if ( bp_is_group() && $parent_slug === groups_get_current_group()->slug ) {
     160                        $component = 'groups';
     161                }
     162
     163                return $component;
     164        }
     165
     166        public function offsetSet( $offset, $value ) {
     167                $bp = buddypress();
     168
     169                if ( is_array( $value ) ) {
     170                        $value = new self( $value );
     171                }
     172
     173                if ( $offset !== null ) {
     174                        // Set the backcompat_nav
     175                        $this->backcompat_nav[ $offset ] = $value;
     176
     177                        _doing_it_wrong(
     178                                'buddypress()->bp_options_nav',
     179                                __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     180                                '2.6.0'
     181                        );
     182
     183                        // This should never be the case!
     184                        if ( ! isset( $bp->members->nav ) ) {
     185                                return;
     186                        }
     187
     188                        // The secondary nav already exists and the user is trying to edit it.
     189                        if ( ! empty( $this->backcompat_nav['slug'] ) ) {
     190                                $parent_slug = $this->get_parent_slug( $this->backcompat_nav, $offset );
     191
     192                                $secondary_nav = $bp->{$this->get_component( $parent_slug )}->nav->get_secondary( array(
     193                                        'parent_slug' => $parent_slug,
     194                                        'slug'        => $this->backcompat_nav['slug']
     195                                ), false );
     196
     197                                // Primary nav item exists, so edit it!
     198                                if ( ! empty( $secondary_nav ) ) {
     199                                        $secondary_nav = reset( $secondary_nav );
     200                                        $bp->{$this->get_component( $parent_slug )}->nav->edit_nav( (array) $this->backcompat_nav, $secondary_nav->slug, $secondary_nav->parent_slug );
     201                                }
     202                        } else if ( ! empty( $value->backcompat_nav ) && isset( $value['slug'] ) ) {
     203                                $parent_slug = $this->get_parent_slug( $value->backcompat_nav, $offset );
     204
     205                                if ( $parent_slug ) {
     206                                        $value->backcompat_nav['parent_slug'] = $parent_slug;
     207                                        $bp->{$this->get_component( $parent_slug )}->nav->add_nav( $value->backcompat_nav );
     208                                }
     209                        }
     210                }
     211        }
     212
     213        public function offsetGet( $offset ) {
     214                $bp = buddypress();
     215
     216                if ( isset( $bp->members->nav ) ) {
     217                        $nav_items = $bp->members->nav->get();
     218
     219                        if ( bp_is_group() ) {
     220                                $nav_items = array_merge( $nav_items, $bp->groups->nav->get_secondary( array( 'parent_slug' => groups_get_current_group()->slug ), false ) );
     221                        }
     222
     223                        foreach ( $nav_items as $nav_item ) {
     224                                if ( ! empty( $nav_item->secondary ) ) {
     225                                        $this->backcompat_nav[ $nav_item->slug ] = new self( (array) $nav_item );
     226                                        $this->backcompat_nav[ $nav_item->parent_slug ] = new self( $this->backcompat_nav[ $nav_item->slug ] );
     227                                }
     228                        }
     229                }
     230
     231                if ( ! isset( $this->backcompat_nav[ $offset ] ) ) {
     232                        $this->backcompat_nav[ $offset ] = new self;
     233                }
     234
     235                _doing_it_wrong(
     236                        'buddypress()->bp_options_nav',
     237                        __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ),
     238                        '2.6.0'
     239                );
     240
     241                return $this->backcompat_nav[ $offset ];
     242        }
     243}
  • src/bp-core/classes/class-bp-core-nav.php

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

    diff --git src/bp-core/deprecated/2.6.php src/bp-core/deprecated/2.6.php
    index acc5e23..3c289b2 100644
    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        return bp_core_add_subnav_item( $args );
     101}
     102
     103/**
     104 * Sort all subnavigation arrays.
     105 *
     106 * @since 1.1.0
     107 * @deprecated 2.6.0
     108 *
     109 * @return bool|null Returns false on failure.
     110 */
     111function bp_core_sort_subnav_items() {
     112        _deprecated_function( __FUNCTION__, '2.6' );
     113}
     114
     115/**
     116 * Remove a nav item from the navigation array.
     117 *
     118 * @since 1.0.0
     119 * @deprecated 2.6.0
     120 *
     121 * @param int $parent_id The slug of the parent navigation item.
     122 * @return bool Returns false on failure, ie if the nav item can't be found.
     123 */
     124function bp_core_remove_nav_item( $parent_id ) {
     125        $bp = buddypress();
     126
     127        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_nav_item()' );
     128
     129        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     130
     131                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     132                        return bp_core_delete_nav_item( $parent_id, 'groups' );
     133                }
     134        }
     135
     136        return bp_core_delete_nav_item( $parent_id );
     137}
     138
     139/**
     140 * Remove a subnav item from the navigation array.
     141 *
     142 * @since 1.0.0
     143 * @deprecated 2.6.0
     144 *
     145 * @param string $parent_id The slug of the parent navigation item.
     146 * @param string $slug      The slug of the subnav item to be removed.
     147 */
     148function bp_core_remove_subnav_item( $parent_id, $slug ) {
     149        $bp = buddypress();
     150
     151        _deprecated_function( __FUNCTION__, '2.6', 'bp_core_delete_subnav_item()' );
     152
     153        if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) {
     154
     155                if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) {
     156                        return bp_core_delete_subnav_item( $slug, $parent_id, 'groups' );
     157                }
     158        }
     159
     160        return bp_core_delete_subnav_item( $slug, $parent_id );
     161}
  • src/bp-groups/bp-groups-adminbar.php

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

    diff --git src/bp-groups/classes/class-bp-group-extension.php src/bp-groups/classes/class-bp-group-extension.php
    index 5709b0b..7209401 100644
    class BP_Group_Extension { 
    737737                                'screen_function' => array( &$this, '_display_hook' ),
    738738                                'user_has_access' => $user_can_see_nav_item,
    739739                                'no_access_url'   => $group_permalink,
    740                         ) );
     740                        ), 'groups' );
    741741                }
    742742
    743743                // If the user can visit the screen, we register it.
    class BP_Group_Extension { 
    752752                                'screen_function' => array( &$this, '_display_hook' ),
    753753                                'user_has_access' => $user_can_visit,
    754754                                'no_access_url'   => $group_permalink,
    755                         ) );
     755                        ), 'groups' );
    756756
    757757                        // When we are viewing the extension display page, set the title and options title.
    758758                        if ( bp_is_current_action( $this->slug ) ) {
    class BP_Group_Extension { 
    967967                }
    968968
    969969                // Add the tab to the manage navigation.
    970                 bp_core_new_subnav_item( $subnav_args );
     970                bp_core_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 src/bp-groups/classes/class-bp-groups-component.php src/bp-groups/classes/class-bp-groups-component.php
    index 355ab8c..145051d 100644
    class BP_Groups_Component extends BP_Component { 
    253253                        // Check once if the current group has a custom front template.
    254254                        $this->current_group->front_template = bp_groups_get_front_template( $this->current_group );
    255255
     256                        /**
     257                         * Since 2.6.0 The Groups single items are using their own navigation to avoid slug
     258                         * collisions with the displayed user options nav (buddypress()->bp_options_nav)
     259                         * and for more flexibility in future releases.
     260                         */
     261
     262                        // Set the Group's Primary Nav
     263                        $this->nav = new BP_Core_Nav( $this->current_group->id );
     264
    256265                // Set current_group to 0 to prevent debug errors.
    257266                } else {
    258267                        $this->current_group = 0;
    class BP_Groups_Component extends BP_Component { 
    496505                        // Reset sub nav.
    497506                        $sub_nav = array();
    498507
    499                         // Add 'Groups' to the main navigation.
    500                         $main_nav = array(
     508                        /**
     509                         * Set the Current Group's main navigation
     510                         *
     511                         * Since 2.6.0 it's now using its own navigation by passing the
     512                         * component's id as the second argument of bp_core_add_nav_item()
     513                         */
     514                        bp_core_add_nav_item( array(
    501515                                'name'                => __( 'Memberships', 'buddypress' ),
    502516                                'slug'                => $this->current_group->slug,
    503517                                'position'            => -1, // Do not show in BuddyBar.
    504518                                'screen_function'     => 'groups_screen_group_home',
    505519                                'default_subnav_slug' => $this->default_extension,
    506520                                'item_css_id'         => $this->id
    507                         );
     521                        ), 'groups' );
    508522
    509523                        $group_link = bp_get_group_permalink( $this->current_group );
    510524
    class BP_Groups_Component extends BP_Component { 
    675689                                ), $default_params );
    676690                        }
    677691
    678                         parent::setup_nav( $main_nav, $sub_nav );
     692                        foreach( $sub_nav as $nav ) {
     693                                /**
     694                                 * Set the Current Group's sub navigation
     695                                 *
     696                                 * Since 2.6.0 it's now using its own sub navigation by passing it
     697                                 * as the second argument of bp_core_add_subnav_item()
     698                                 */
     699                                bp_core_add_subnav_item( $nav, 'groups' );
     700                        }
    679701                }
    680702
    681703                if ( isset( $this->current_group->user_has_access ) ) {
  • src/bp-loader.php

    diff --git src/bp-loader.php src/bp-loader.php
    index 4a744c4..3ee25b6 100644
    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
  • src/bp-members/bp-members-template.php

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

    diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php
    index 92a2c85..ee77fc9 100644
    class BP_Members_Component extends BP_Component { 
    150150                // The domain for the user currently being displayed.
    151151                $bp->displayed_user->domain   = bp_core_get_user_domain( bp_displayed_user_id() );
    152152
     153                // Backward compatibility for the Displayed User Nav
     154                $bp->bp_nav         = new BP_Core_BackCompat_Nav();
     155                $bp->bp_options_nav = new BP_Core_BackCompat_Options_Nav();
     156
     157                // Set the Nav for the members component
     158                $this->nav = new BP_Core_Nav();
     159
    153160                /** Signup ***********************************************************
    154161                 */
    155162
  • src/bp-messages/bp-messages-screens.php

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

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

    diff --git src/bp-xprofile/classes/class-bp-xprofile-component.php src/bp-xprofile/classes/class-bp-xprofile-component.php
    index a07929b..326465d 100644
    class BP_XProfile_Component extends BP_Component { 
    287287                // Get the settings slug.
    288288                $settings_slug = bp_get_settings_slug();
    289289
    290                 bp_core_new_subnav_item( array(
     290                bp_core_add_subnav_item( array(
    291291                        'name'            => _x( 'Profile Visibility', 'Profile settings sub nav', 'buddypress' ),
    292292                        'slug'            => 'profile',
    293293                        'parent_url'      => trailingslashit( $user_domain . $settings_slug ),
    class BP_XProfile_Component extends BP_Component { 
    295295                        'screen_function' => 'bp_xprofile_screen_settings',
    296296                        'position'        => 30,
    297297                        'user_has_access' => bp_core_can_edit_settings()
    298                 ) );
     298                ), 'members' );
    299299        }
    300300
    301301        /**