Ticket #6534: 6534.05.patch
File 6534.05.patch, 82.1 KB (added by , 7 years ago) |
---|
-
src/bp-core/bp-core-buddybar.php
diff --git src/bp-core/bp-core-buddybar.php src/bp-core/bp-core-buddybar.php index 9f1ffb0..f20fcf3 100644
13 13 defined( 'ABSPATH' ) || exit; 14 14 15 15 /** 16 * Add an item to the main BuddyPress navigation array.16 * Add an item to the primary navigation of the specified component. 17 17 * 18 * @since 1.1.018 * @since 2.6.0 19 19 * 20 20 * @param array|string $args { 21 21 * Array describing the new nav item. … … defined( 'ABSPATH' ) || exit; 32 32 * @type bool|string $default_subnav_slug Optional. The slug of the default subnav item to select when the nav 33 33 * item is clicked. 34 34 * } 35 * @param string $component The component the navigation is attached to. Defaults to 'members'. 35 36 * @return bool|null Returns false on failure. 36 37 */ 37 function bp_core_new_nav_item( $args = '' ) { 38 39 function bp_core_add_nav_item( $args, $component = 'members' ) { 40 if ( ! bp_is_active( $component ) ) { 41 return; 42 } 38 43 39 44 $defaults = array( 40 45 'name' => false, // Display name for the nav item. … … function bp_core_new_nav_item( $args = '' ) { 49 54 50 55 $r = wp_parse_args( $args, $defaults ); 51 56 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 ); 54 70 55 71 // To mimic the existing behavior, if bp_core_create_nav_link() 56 72 // returns false, we make an early exit and don't attempt to register 57 73 // the screen function. 58 if ( false === $ created) {74 if ( false === $nav_item ) { 59 75 return false; 60 76 } 61 77 62 78 // 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 ); 64 80 if ( false === $hooked ){ 65 81 return false; 66 82 } 67 83 84 // Add the item to the nav 85 buddypress()->{$component}->nav->add_nav( $nav_item ); 86 68 87 /** 69 88 * Fires after adding an item to the main BuddyPress navigation array. 70 89 * Note that, when possible, the more specific action hooks … … function bp_core_create_nav_link( $args = '' ) { 132 151 $r['item_css_id'] = $r['slug']; 133 152 } 134 153 135 $bp->bp_nav[$r['slug']] =array(154 return array( 136 155 'name' => $r['name'], 137 156 'slug' => $r['slug'], 138 157 'link' => trailingslashit( bp_loggedin_user_domain() . $r['slug'] ), … … function bp_core_create_nav_link( $args = '' ) { 142 161 'screen_function' => &$r['screen_function'], 143 162 'default_subnav_slug' => $r['default_subnav_slug'] 144 163 ); 145 146 /**147 * Fires after a link is added to the main BuddyPress navigation array.148 *149 * @since 2.4.0150 *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 );156 164 } 157 165 158 166 /** … … function bp_core_new_nav_default( $args = '' ) { 290 298 291 299 $r = wp_parse_args( $args, $defaults ); 292 300 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 ) ) { 294 311 // 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 ); 297 314 } 298 315 } 299 316 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 ); 301 322 302 if ( bp_is_current_component( $ r['parent_slug']) ) {323 if ( bp_is_current_component( $parent_nav->slug ) ) { 303 324 304 325 // The only way to tell whether to set the subnav is to peek at the unfiltered_uri 305 326 // 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 ); 307 328 308 329 if ( false !== $component_uri_key ) { 309 330 if ( ! empty( $bp->unfiltered_uri[$component_uri_key + 1] ) ) { … … function bp_core_new_nav_default( $args = '' ) { 339 360 } 340 361 341 362 /** 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. 381 364 * 382 * @since 1.1.0365 * @since 2.6.0 383 366 * 384 367 * @param array|string $args { 385 368 * Array describing the new subnav item. … … add_action( 'admin_head', 'bp_core_sort_nav_items' ); 403 386 * @type bool $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit" 404 387 * Admin Bar menu for group admins. Default: false. 405 388 * } 389 * @param string $component The component the navigation is attached to. Defaults to 'members'. 406 390 * @return bool|null Returns false on failure. 407 391 */ 408 function bp_core_new_subnav_item( $args = '' ) { 392 function bp_core_add_subnav_item( $args, $component = 'members' ) { 393 if ( ! bp_is_active( $component ) ) { 394 return; 395 } 409 396 410 397 // 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 ); 412 399 413 400 // To mimic the existing behavior, if bp_core_create_subnav_link() 414 401 // returns false, we make an early exit and don't attempt to register 415 402 // the screen function. 416 if ( false === $ created) {403 if ( false === $subnav_item ) { 417 404 return false; 418 405 } 419 406 420 407 // 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 ); 422 409 if ( false === $hooked ) { 423 410 return false; 424 411 } … … function bp_core_new_subnav_item( $args = '' ) { 428 415 * Add a subnav link to the BuddyPress navigation. 429 416 * 430 417 * @since 2.4.0 418 * @since 2.6.0 Adds the $component parameter. 431 419 * 432 420 * @param array|string $args { 433 421 * Array describing the new subnav item. … … function bp_core_new_subnav_item( $args = '' ) { 455 443 * the group's "Edit" Admin Bar menu for group admins. 456 444 * Default: false. 457 445 * } 446 * @param string $component The component the navigation is attached to. Defaults to 'members'. 458 447 * @return bool|null Returns false on failure. 459 448 */ 460 function bp_core_create_subnav_link( $args = '' ) {449 function bp_core_create_subnav_link( $args = '', $component = 'members' ) { 461 450 $bp = buddypress(); 462 451 463 452 $r = wp_parse_args( $args, array( … … function bp_core_create_subnav_link( $args = '' ) { 483 472 if ( empty( $r['link'] ) ) { 484 473 $r['link'] = trailingslashit( $r['parent_url'] . $r['slug'] ); 485 474 475 $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false ); 476 486 477 // 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 ) { 488 479 $r['link'] = trailingslashit( $r['parent_url'] ); 489 480 } 490 481 } … … function bp_core_create_subnav_link( $args = '' ) { 502 493 'name' => $r['name'], 503 494 'link' => $r['link'], 504 495 'slug' => $r['slug'], 496 'parent_slug' => $r['parent_slug'], 505 497 'css_id' => $r['item_css_id'], 506 498 'position' => $r['position'], 507 499 'user_has_access' => $r['user_has_access'], … … function bp_core_create_subnav_link( $args = '' ) { 510 502 'show_in_admin_bar' => (bool) $r['show_in_admin_bar'], 511 503 ); 512 504 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; 514 508 } 515 509 516 510 /** 517 511 * Register a screen function, whether or not a related subnav link exists. 518 512 * 519 513 * @since 2.4.0 514 * @since 2.6.0 Adds the $component parameter. 520 515 * 521 516 * @param array|string $args { 522 517 * Array describing the new subnav item. … … function bp_core_create_subnav_link( $args = '' ) { 541 536 * the group's "Edit" Admin Bar menu for group admins. 542 537 * Default: false. 543 538 * } 539 * @param string $component The component the navigation is attached to. Defaults to 'members'. 544 540 * @return bool|null Returns false on failure. 545 541 */ 546 function bp_core_register_subnav_screen_function( $args = '' ) {542 function bp_core_register_subnav_screen_function( $args = '', $component = 'members' ) { 547 543 $bp = buddypress(); 548 544 549 545 $r = wp_parse_args( $args, array( … … function bp_core_register_subnav_screen_function( $args = '' ) { 568 564 * (b) there is no current_action (ie, this is the default subnav for the parent nav) 569 565 * and this subnav item is the default for the parent item (which we check by 570 566 * 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 a567 * parent nav item in the component's primary nav). This condition only arises when viewing a 572 568 * user, since groups should always have an action set. 573 569 */ 574 570 … … function bp_core_register_subnav_screen_function( $args = '' ) { 577 573 return; 578 574 } 579 575 576 $parent_nav = $bp->{$component}->nav->get_primary( array( 'slug' => $r['parent_slug'] ), false ); 577 580 578 // 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() && ! empty( $parent_nav->screen_function ) && $r['screen_function'] == $parent_nav->screen_function ) ) { 582 580 583 581 // If this is for site admins only and the user is not one, don't create the subnav item. 584 582 if ( ! empty( $r['site_admin_only'] ) && ! bp_current_user_can( 'bp_moderate' ) ) { 585 583 return false; 586 584 } 587 585 588 $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r );586 $hooked = bp_core_maybe_hook_new_subnav_screen_function( $r, $component ); 589 587 590 588 // If redirect args have been returned, perform the redirect now. 591 589 if ( ! empty( $hooked['status'] ) && 'failure' === $hooked['status'] && isset( $hooked['redirect_args'] ) ) { … … function bp_core_register_subnav_screen_function( $args = '' ) { 598 596 * For a given subnav item, either hook the screen function or generate redirect arguments, as necessary. 599 597 * 600 598 * @since 2.1.0 599 * @since 2.6.0 Adds the $component parameter. 601 600 * 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'. 603 603 * @return array 604 604 */ 605 function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) {605 function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item, $component = 'members' ) { 606 606 $retval = array( 607 607 'status' => '', 608 608 ); … … function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 645 645 // redirect URL. 646 646 } elseif ( bp_is_user() ) { 647 647 648 $parent_nav_default = $bp->{$component}->nav->get_primary( array( 'slug' => $bp->default_component ), false ); 649 648 650 // Redirect to the displayed user's default 649 651 // component, as long as that component is 650 652 // 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 ) ) { 652 654 $message = __( 'You do not have access to this page.', 'buddypress' ); 653 655 $redirect_to = bp_displayed_user_domain(); 654 656 … … function bp_core_maybe_hook_new_subnav_screen_function( $subnav_item ) { 691 693 } 692 694 693 695 /** 694 * Sort all subnavigation arrays.696 * Check whether a given nav item has subnav items. 695 697 * 696 * @since 1.1.0 698 * @since 1.5.0 699 * @since 2.6.0 Adds the $component parameter. 697 700 * 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. 699 705 */ 700 function bp_ core_sort_subnav_items() {706 function bp_nav_item_has_subnav( $nav_item = '', $component = 'members' ) { 701 707 $bp = buddypress(); 702 708 703 if ( empty( $bp->bp_options_nav ) || !is_array( $bp->bp_options_nav ) )709 if ( ! isset( $bp->{$component}->nav ) ) { 704 710 return false; 711 } 705 712 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(); 718 715 719 $temp[$subnav_item['position']] = $subnav_item;720 }716 if ( bp_is_group() ) { 717 $nav_item = bp_current_item(); 721 718 } 722 ksort( $temp );723 $bp->bp_options_nav[$parent_slug] = &$temp;724 unset( $temp );725 719 } 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.0734 *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();744 720 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 ); 746 722 747 723 /** 748 724 * Filters whether or not a given nav item has subnav items. … … function bp_nav_item_has_subnav( $nav_item = '' ) { 756 732 } 757 733 758 734 /** 759 * Remove a nav item from the navigation array.735 * Deletes an item from the primary navigation of the specified component. 760 736 * 761 * @since 1.0.0737 * @since 2.6.0 762 738 * 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. 765 742 */ 766 function bp_core_ remove_nav_item( $parent_id) {743 function bp_core_delete_nav_item( $slug, $component = 'members' ) { 767 744 $bp = buddypress(); 768 745 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; 774 748 } 775 749 776 if ( empty( $bp->bp_nav[ $parent_id ] ) ) 750 $screen_functions = $bp->{$component}->nav->delete_nav( $slug ); 751 752 if ( ! is_array( $screen_functions ) ) { 777 753 return false; 754 } 778 755 779 if ( $function = $bp->bp_nav[$parent_id]['screen_function']) {756 foreach ( $screen_functions as $screen_function ) { 780 757 // 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 ); 783 760 } 784 761 } 785 762 786 unset( $bp->bp_nav[$parent_id] );763 return true; 787 764 } 788 765 789 766 /** 790 * Remove a subnav item from the navigation array.767 * Deletes an item from the secondary navigation of the specified component. 791 768 * 792 * @since 1.0.0769 * @since 2.6.0 793 770 * 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. 796 775 */ 797 function bp_core_ remove_subnav_item( $parent_id, $slug) {776 function bp_core_delete_subnav_item( $slug, $parent_slug, $component = 'members' ) { 798 777 $bp = buddypress(); 799 778 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 } 803 782 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; 809 787 } 810 788 811 unset( $bp->bp_options_nav[$parent_id][$slug]);789 $screen_function = reset( $screen_functions ); 812 790 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; 815 797 } 816 798 817 799 /** 818 800 * Clear all subnav items from a specific nav item. 819 801 * 820 802 * @since 1.0.0 803 * @since 2.6.0 Adds the $component parameter. 821 804 * 822 805 * @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'. 823 807 */ 824 function bp_core_reset_subnav_items( $parent_slug ) {808 function bp_core_reset_subnav_items( $parent_slug, $component = 'members' ) { 825 809 $bp = buddypress(); 826 810 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 } 828 824 } 829 825 830 826 -
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' ); 684 684 * 685 685 * @see BP_Members_Component::setup_globals() where 686 686 * $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. 688 688 * @uses bp_get_canonical_url() 689 689 * @uses bp_get_requested_url() 690 690 */ -
src/bp-core/bp-core-classes.php
diff --git src/bp-core/bp-core-classes.php src/bp-core/bp-core-classes.php index bebf4ed..9d2d377 100644
require dirname( __FILE__ ) . '/classes/class-bp-email-recipient.php'; 30 30 require dirname( __FILE__ ) . '/classes/class-bp-email.php'; 31 31 require dirname( __FILE__ ) . '/classes/class-bp-email-delivery.php'; 32 32 require dirname( __FILE__ ) . '/classes/class-bp-phpmailer.php'; 33 require dirname( __FILE__ ) . '/classes/class-bp-core-nav.php'; 34 require dirname( __FILE__ ) . '/classes/class-bp-core-nav-item.php'; 35 36 if ( buddypress()->do_nav_backcompat ) { 37 require dirname( __FILE__ ) . '/classes/class-bp-core-bp-nav-backcompat.php'; 38 require dirname( __FILE__ ) . '/classes/class-bp-core-bp-options-nav-backcompat.php'; 39 } -
src/bp-core/bp-core-functions.php
diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php index 702d0dd..ea81687 100644
function bp_nav_menu_get_loggedin_pages() { 2443 2443 return buddypress()->wp_nav_menu_items->loggedin; 2444 2444 } 2445 2445 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(); 2451 2448 2452 2449 // Some BP nav menu items will not be represented in bp_nav, because 2453 2450 // they are not real BP components. We add them manually here. 2454 $bp_menu_items[] = array(2451 $bp_menu_items[] = (object) array( 2455 2452 'name' => __( 'Log Out', 'buddypress' ), 2456 2453 'slug' => 'logout', 2457 2454 'link' => wp_logout_url(), … … function bp_nav_menu_get_loggedin_pages() { 2467 2464 foreach ( $bp_menu_items as $bp_item ) { 2468 2465 2469 2466 // 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 ); 2471 2468 2472 $page_args[ $bp_item ['slug']] = (object) array(2469 $page_args[ $bp_item->slug ] = (object) array( 2473 2470 'ID' => -1, 2474 2471 'post_title' => $item_name, 2475 2472 'post_author' => 0, 2476 2473 'post_date' => 0, 2477 'post_excerpt' => $bp_item ['slug'],2474 'post_excerpt' => $bp_item->slug, 2478 2475 'post_type' => 'page', 2479 2476 'post_status' => 'publish', 2480 2477 'comment_status' => 'closed', 2481 'guid' => $bp_item ['link']2478 'guid' => $bp_item->link 2482 2479 ); 2483 2480 } 2484 2481 … … function bp_nav_menu_get_loggedout_pages() { 2575 2572 * @since 1.9.0 2576 2573 * 2577 2574 * @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. 2579 2576 * @return string $nav_item_url The URL generated for the current user. 2580 2577 */ 2581 2578 function 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; 13 13 /** 14 14 * Output the "options nav", the secondary-level single item navigation menu. 15 15 * 16 * Uses the $bp->bp_options_nav global to render out the sub navigation for the16 * Uses the component's nav global to render out the sub navigation for the 17 17 * current component. Each component adds to its sub navigation array within 18 18 * its own setup_nav() function. 19 19 * … … function bp_get_options_nav( $parent_slug = '' ) { 40 40 $component_index = !empty( $bp->displayed_user ) ? bp_current_component() : bp_get_root_slug( bp_current_component() ); 41 41 $selected_item = bp_current_action(); 42 42 43 /** 44 * Use the members Nav 45 */ 43 46 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 ) { 45 55 return false; 46 } else {47 $the_index = $component_index;48 56 } 57 58 /** 59 * Try to use the component's Nav for the single item. 60 */ 49 61 } else { 50 62 $current_item = bp_current_item(); 63 $single_item_component = bp_current_component(); 51 64 65 // Adjust the selected nav item for the current single item if needed 52 66 if ( ! empty( $parent_slug ) ) { 53 67 $current_item = $parent_slug; 54 68 $selected_item = bp_action_variable( 0 ); 55 69 } 56 70 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 ) ); 59 74 } 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; 61 80 } 62 81 } 63 82 64 83 // 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 ) ) { 67 86 continue; 68 87 } 69 88 70 89 // 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 ) { 72 91 $selected = ' class="current selected"'; 73 92 } else { 74 93 $selected = ''; … … function bp_get_options_nav( $parent_slug = '' ) { 88 107 * @param array $subnav_item Submenu array item being displayed. 89 108 * @param string $selected_item Current action. 90 109 */ 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 ); 92 111 } 93 112 } 94 113 … … function bp_get_title_parts( $seplocation = 'right' ) { 3010 3029 // Set empty subnav name. 3011 3030 $component_subnav_name = ''; 3012 3031 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 3013 3037 // 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 ); 3016 3040 3017 3041 // Fall back on the component ID. 3018 3042 } elseif ( ! empty( $bp->{$component_id}->id ) ) { 3019 3043 $component_name = ucwords( $bp->{$component_id}->id ); 3020 3044 } 3021 3045 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 ); 3025 3051 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 ); 3028 3054 } 3029 3055 } 3030 3056 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 3031 3062 // If on the user profile's landing page, just use the fullname. 3032 3063 if ( bp_is_current_component( $bp->default_component ) && ( bp_get_requested_url() === bp_displayed_user_domain() ) ) { 3033 3064 $bp_title_parts[] = $displayed_user_name; … … function bp_get_title_parts( $seplocation = 'right' ) { 3045 3076 } 3046 3077 } 3047 3078 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. 3054 3080 } 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 ); 3056 3101 3057 3102 // An index or directory. 3058 3103 } elseif ( bp_is_directory() ) { … … function _bp_nav_menu_sort( $a, $b ) { 3428 3473 * Get the items registered in the primary and secondary BuddyPress navigation menus. 3429 3474 * 3430 3475 * @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 3431 3477 * 3432 3478 * @return array A multidimensional array of all navigation items. 3433 3479 */ 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 } 3480 function bp_get_nav_menu_items( $component = 'members' ) { 3481 $bp = buddypress(); 3482 $menus = array(); 3444 3483 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; 3473 3486 } 3474 3487 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 ) { 3487 3490 // 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 ); 3489 3492 3490 3493 // Add this menu. 3491 3494 $menu = new stdClass; 3492 3495 $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; 3496 3499 $menu->parent = 0; 3497 3500 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 } 3501 3520 } 3502 3521 3503 3522 $menus[] = $menu; 3523 3524 if ( ! empty( $submenus ) ) { 3525 $menus = array_merge( $menus, $submenus ); 3526 } 3504 3527 } 3505 3528 3506 3529 /** -
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 { 473 473 * Set up component navigation. 474 474 * 475 475 * @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) 476 478 * 477 * @see bp_core_ new_nav_item() For a description of the $main_nav479 * @see bp_core_add_nav_item() For a description of the $main_nav 478 480 * parameter formatting. 479 * @see bp_core_ new_subnav_item() For a description of how each item481 * @see bp_core_add_subnav_item() For a description of how each item 480 482 * in the $sub_nav parameter array should be formatted. 481 483 * 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(). 483 485 * See that function for a description. 484 486 * @param array $sub_nav Optional. Multidimensional array, each item in 485 * which is passed to bp_core_ new_subnav_item(). See that487 * which is passed to bp_core_add_subnav_item(). See that 486 488 * function for a description. 487 489 */ 488 490 public function setup_nav( $main_nav = array(), $sub_nav = array() ) { 489 491 490 492 // No sub nav items without a main nav item. 491 493 if ( !empty( $main_nav ) ) { 492 bp_core_ new_nav_item( $main_nav);494 bp_core_add_nav_item( $main_nav, 'members' ); 493 495 494 496 // Sub nav items are not required. 495 497 if ( !empty( $sub_nav ) ) { 496 498 foreach( (array) $sub_nav as $nav ) { 497 bp_core_ new_subnav_item( $nav);499 bp_core_add_subnav_item( $nav, 'members' ); 498 500 } 499 501 } 500 502 } -
new file src/bp-core/classes/class-bp-core-bp-nav-backcompat.php
diff --git src/bp-core/classes/class-bp-core-bp-nav-backcompat.php src/bp-core/classes/class-bp-core-bp-nav-backcompat.php new file mode 100644 index 0000000..e7231a7
- + 1 <?php 2 /** 3 * Backward compatibility for the $bp->bp_nav global. 4 * 5 * @since 2.6.0 6 */ 7 8 // Exit if accessed directly. 9 defined( 'ABSPATH' ) || exit; 10 11 /** 12 * bp_nav backward compatibility class. 13 * 14 * This class is used to provide backward compatibility for extensions that access and modify 15 * the $bp->bp_nav global. 16 * 17 * @since 2.6.0 18 */ 19 class BP_Core_BP_Nav_BackCompat implements ArrayAccess { 20 public $backcompat_nav = array(); 21 public $component; 22 23 public function __construct( $backcompat_nav = array() ) { 24 foreach ( $backcompat_nav as $key => $value ) { 25 if ( is_array( $value ) ) { 26 $this->backcompat_nav[ $key ] = new self( $value ); 27 } else { 28 $this->backcompat_nav[ $key ] = $value; 29 } 30 } 31 } 32 33 public function offsetSet( $offset, $value ) { 34 _doing_it_wrong( 35 'bp_nav', 36 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 37 '2.6.0' 38 ); 39 40 $bp = buddypress(); 41 42 if ( is_array( $value ) ) { 43 $value = new self( $value ); 44 } 45 46 if ( $offset !== null ) { 47 // Temporarily set the backcompat_nav. 48 $this->backcompat_nav[ $offset ] = $value; 49 50 $args = $this->to_array(); 51 if ( isset( $args['parent_slug'] ) ) { 52 $this->get_component_nav( $args['parent_slug'] )->edit_nav( $args, $args['slug'], $args['parent_slug'] ); 53 } elseif ( isset( $args['slug'] ) ) { 54 $bp->members->nav->edit_nav( $args, $args['slug'] ); 55 } 56 } 57 } 58 59 public function offsetGet( $offset ) { 60 _doing_it_wrong( 61 'bp_nav', 62 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 63 '2.6.0' 64 ); 65 66 if ( ! isset( $this->backcompat_nav[ $offset ] ) ) { 67 $nav = $this->get_nav( $offset ); 68 if ( $nav && isset( $nav[ $offset ] ) ) { 69 $this->backcompat_nav[ $offset ] = new self( $nav[ $offset ] ); 70 } 71 } 72 73 return $this->backcompat_nav[ $offset ]; 74 } 75 76 public function offsetExists( $offset ) { 77 _doing_it_wrong( 78 'bp_nav', 79 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 80 '2.6.0' 81 ); 82 83 if ( isset( $this->backcompat_nav[ $offset ] ) ) { 84 return true; 85 } 86 87 $nav = $this->get_nav( $offset ); 88 if ( $nav && isset( $nav[ $offset ] ) ) { 89 return true; 90 } 91 92 return false; 93 } 94 95 public function offsetUnset( $offset ) { 96 _doing_it_wrong( 97 'bp_nav', 98 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 99 '2.6.0' 100 ); 101 102 // For top-level nav items, the backcompat nav hasn't yet been initialized. 103 if ( ! isset( $this->backcompat_nav[ $offset ] ) ) { 104 buddypress()->members->nav->delete_nav( $offset ); 105 unset( $this->backcompat_nav[ $offset ] ); 106 } 107 } 108 109 public function get_nav( $offset ) { 110 $bp = buddypress(); 111 112 $component_nav = $this->get_component_nav( $offset ); 113 $primary_nav = $component_nav->get_primary( array( 'slug' => $offset ), false ); 114 115 $nav = array(); 116 117 if ( empty( $primary_nav ) ) { 118 return $nav; 119 } 120 121 foreach ( $primary_nav as $item ) { 122 $nav[ $item->slug ] = (array) $item; 123 } 124 125 return $nav; 126 } 127 128 public function set_component( $component ) { 129 $this->component = $component; 130 } 131 132 public function get_component( $offset = '' ) { 133 if ( ! isset( $this->component ) ) { 134 if ( bp_is_active( 'groups' ) && $offset === bp_get_current_group_slug() ) { 135 $this->component = 'groups'; 136 } else { 137 $this->component = 'members'; 138 } 139 } 140 141 return $this->component; 142 } 143 144 protected function to_array() { 145 return $this->backcompat_nav; 146 } 147 148 /** 149 * Get the BP_Core_Nav object corresponding to the component, based on a nav item name. 150 * 151 * The way bp_nav was previously organized makes it impossible to know for sure which component's nav is 152 * being referenced by a given nav item name. We guess in the following manner: 153 * - If we're looking at a group, and the nav item name (`$offset`) is the same as the slug of the current 154 * group, we assume that the proper component nav is 'groups'. 155 * - Otherwise, fall back on 'members'. 156 * 157 * @since 2.6.0 158 * 159 * @param string $offset Nav item name. 160 * @return BP_Core_Nav 161 */ 162 protected function get_component_nav( $offset = '' ) { 163 $component = $this->get_component( $offset ); 164 165 $bp = buddypress(); 166 if ( ! isset( $bp->{$component}->nav ) ) { 167 return false; 168 } 169 170 return $bp->{$component}->nav; 171 } 172 } -
new file src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php
diff --git src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php src/bp-core/classes/class-bp-core-bp-options-nav-backcompat.php new file mode 100644 index 0000000..ac84b4c
- + 1 <?php 2 /** 3 * Backward compatibility for the $bp->bp_options_nav global. 4 * 5 * @since 2.6.0 6 */ 7 8 // Exit if accessed directly. 9 defined( 'ABSPATH' ) || exit; 10 11 /** 12 * bp_options_nav backward compatibility class. 13 * 14 * This class is used to provide backward compatibility for extensions that access and modify 15 * the $bp->bp_options_nav global. 16 * 17 * @since 2.6.0 18 */ 19 class BP_Core_BP_Options_Nav_BackCompat extends BP_Core_BP_Nav_BackCompat { 20 protected $parent_slug = ''; 21 22 public function offsetGet( $offset ) { 23 _doing_it_wrong( 24 'bp_nav', 25 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 26 '2.6.0' 27 ); 28 29 if ( empty( $this->backcompat_nav[ $offset ] ) ) { 30 $nav = $this->get_nav( $offset ); 31 if ( $nav ) { 32 $subnavs = $this->get_component_nav( $offset )->get_secondary( array( 'parent_slug' => $offset ) ); 33 $subnav_keyed = array(); 34 foreach ( $subnavs as $subnav ) { 35 $subnav_keyed[ $subnav->slug ] = (array) $subnav; 36 } 37 38 $subnav_object = new self( $subnav_keyed ); 39 $subnav_object->set_component( $this->get_component() ); 40 $subnav_object->set_parent_slug( $offset ); 41 42 $this->backcompat_nav[ $offset ] = $subnav_object; 43 } 44 } 45 return $this->backcompat_nav[ $offset ]; 46 } 47 48 public function offsetUnset( $offset ) { 49 _doing_it_wrong( 50 'bp_nav', 51 __( 'These globals should not be used directly and are deprecated. Please use the BuddyPress nav functions instead.', 'buddypress' ), 52 '2.6.0' 53 ); 54 55 $this->get_component_nav( $offset )->delete_nav( $offset, $this->get_parent_slug() ); 56 57 // Clear the cached nav. 58 unset( $this->backcompat_nav[ $offset ] ); 59 } 60 61 public function get_parent_slug() { 62 return $this->parent_slug; 63 } 64 65 public function set_parent_slug( $slug ) { 66 $this->parent_slug = $slug; 67 } 68 } -
new file src/bp-core/classes/class-bp-core-nav-item.php
diff --git src/bp-core/classes/class-bp-core-nav-item.php src/bp-core/classes/class-bp-core-nav-item.php new file mode 100644 index 0000000..8b901b3
- + 1 <?php 2 3 // Exit if accessed directly. 4 defined( 'ABSPATH' ) || exit; 5 6 if ( class_exists( 'ArrayObject' ) ) : 7 8 /** 9 * Navigation item. 10 * 11 * @since 2.6.0 12 */ 13 class BP_Core_Nav_Item extends ArrayObject { 14 public function __construct( $data ) { 15 parent::__construct( $data, ArrayObject::ARRAY_AS_PROPS ); 16 } 17 } 18 19 else : 20 21 /** 22 * Navigation item. 23 * 24 * @since 2.6.0 25 */ 26 class BP_Core_Nav_Item { 27 public function __construct( $data ) { 28 foreach ( $data as $key => $value ) { 29 $this->key = $value; 30 } 31 } 32 } 33 34 endif; -
new file src/bp-core/classes/class-bp-core-nav.php
diff --git src/bp-core/classes/class-bp-core-nav.php src/bp-core/classes/class-bp-core-nav.php new file mode 100644 index 0000000..03eb5b1
- + 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. 11 defined( '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 */ 20 class 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 ] = new BP_Core_Nav_Item( $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 ] = new BP_Core_Nav_Item( $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 ] = new BP_Core_Nav_Item( 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 ] = new BP_Core_Nav_Item( $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 219 // Validate the subnav 220 $sub_items = $this->get_secondary( array( 'parent_slug' => $parent_slug, 'slug' => $slug ), false ); 221 222 if ( ! $sub_items ) { 223 return false; 224 } 225 226 $sub_item = reset( $sub_items ); 227 228 if ( empty( $sub_item->slug ) ) { 229 return false; 230 } 231 232 // Delete the child 233 unset( $this->nav[ $this->item_id ][ $parent_slug . '/' . $slug ] ); 234 235 // Return the deleted item's screen function 236 return array( $sub_item->screen_function ); 237 238 // We're deleting a parent 239 } else { 240 // Validate the nav 241 $nav_items = $this->get_primary( array( 'slug' => $slug ), false ); 242 243 if ( ! $nav_items ) { 244 return false; 245 } 246 247 $nav_item = reset( $nav_items ); 248 249 if ( empty( $nav_item->slug ) ) { 250 return false; 251 } 252 253 $screen_functions = array( $nav_item->screen_function ); 254 255 // Life's unfair, children won't survive the parent :( 256 $sub_items = $this->get_secondary( array( 'parent_slug' => $nav_item->slug ), false ); 257 258 if ( ! empty( $sub_items ) ) { 259 foreach ( $sub_items as $sub_item ) { 260 $screen_functions[] = $sub_item->screen_function; 261 262 // Delete the child 263 unset( $this->nav[ $this->item_id ][ $nav_item->slug . '/' . $sub_item->slug ] ); 264 } 265 } 266 267 // Delete the parent 268 unset( $this->nav[ $this->item_id ][ $nav_item->slug ] ); 269 270 // Return the deleted item's screen functions 271 return array_unique( $screen_functions ); 272 } 273 } 274 275 /** 276 * Sorts a list of nav items. 277 * 278 * @since 2.6.0 279 * 280 * @param array $items The nav item's to sort. 281 */ 282 public function sort_nav( $items ) { 283 $sorted = array(); 284 285 foreach ( $items as $item ) { 286 // Default position 287 $position = 99; 288 289 if ( isset( $item->position ) ) { 290 $position = (int) $item->position; 291 } 292 293 // If position is already taken, move to the first next available 294 if ( isset( $sorted[ $position ] ) ) { 295 $sorted_keys = array_keys( $sorted ); 296 297 do { 298 $position += 1; 299 } while ( in_array( $position, $sorted_keys ) ); 300 } 301 302 $sorted[ $position ] = $item; 303 } 304 305 ksort( $sorted ); 306 return $sorted; 307 } 308 309 /** 310 * Gets the primary nav items. 311 * 312 * @since 2.6.0 313 * 314 * @param array $args Filters to select the specific primary items. 315 * @param bool $sort True to sort the nav items. False otherwise. 316 * @return array The list of primary objects nav 317 */ 318 public function get_primary( $args = array(), $sort = true ) { 319 $params = wp_parse_args( $args, array( 'primary' => true ) ); 320 321 // This parameter is not overridable 322 if ( empty( $params['primary'] ) ) { 323 return false; 324 } 325 326 $primary_nav = wp_list_filter( $this->nav[ $this->item_id ], $params ); 327 328 if ( ! $primary_nav ) { 329 return false; 330 } 331 332 if ( true !== $sort ) { 333 return $primary_nav; 334 } 335 336 return $this->sort_nav( $primary_nav ); 337 } 338 339 /** 340 * Gets the secondary nav items. 341 * 342 * @since 2.6.0 343 * 344 * @param array $args Filters to select the specific secondary items. 345 * @param bool $sort True to sort the nav items. False otherwise. 346 * @return array The list of secondary objects nav 347 */ 348 public function get_secondary( $args = array(), $sort = true ) { 349 $params = wp_parse_args( $args, array( 'parent_slug' => '' ) ); 350 351 // No need to search children if the parent is not set 352 if ( empty( $params['parent_slug'] ) && empty( $params['secondary'] ) ) { 353 return false; 354 } 355 356 $secondary_nav = wp_list_filter( $this->nav[ $this->item_id ], $params ); 357 358 if ( ! $secondary_nav ) { 359 return false; 360 } 361 362 if ( true !== $sort ) { 363 return $secondary_nav; 364 } 365 366 return $this->sort_nav( $secondary_nav ); 367 } 368 369 /** 370 * Gets a nested list of visible nav items. 371 * 372 * @since 2.6.0 373 * 374 * @return array The list of visible objects nav 375 */ 376 public function get_item_nav() { 377 $primary_nav_items = $this->get_primary( array( 'show_for_displayed_user' => true ) ); 378 379 if ( $primary_nav_items ) { 380 foreach( $primary_nav_items as $key_nav => $primary_nav ) { 381 // Try to get the children 382 $children = $this->get_secondary( array( 'parent_slug' => $primary_nav->slug, 'user_has_access' => true ) ); 383 384 if ( $children ) { 385 $primary_nav_items[ $key_nav ] = clone( $primary_nav ); 386 $primary_nav_items[ $key_nav ]->children = $children; 387 } 388 } 389 } 390 391 return $primary_nav_items; 392 } 393 } -
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..0dc79f2 100644
function bp_core_print_generation_time() { 21 21 22 22 <?php 23 23 } 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 */ 48 function bp_core_new_nav_item( $args = '' ) { 49 $e = new Exception; 50 $trace = $e->getTraceAsString(); 51 52 _deprecated_function( __FUNCTION__, '2.6', "bp_core_add_nav_item() instead.\n===\nTrace:\n" . $trace . "\n===\n" ); 53 return bp_core_add_nav_item( $args ); 54 } 55 56 /** 57 * Sort the navigation menu items. 58 * 59 * The sorting is split into a separate function because it can only happen 60 * after all plugins have had a chance to register their navigation items. 61 * 62 * @since 1.0.0 63 * @deprecated 2.6.0 64 * 65 * @return bool|null Returns false on failure. 66 */ 67 function bp_core_sort_nav_items() { 68 _deprecated_function( __FUNCTION__, '2.6' ); 69 } 70 71 /** 72 * Add a subnav item to the BuddyPress navigation. 73 * 74 * @since 1.1.0 75 * @deprecated 2.6.0 76 * 77 * @param array|string $args { 78 * Array describing the new subnav item. 79 * @type string $name Display name for the subnav item. 80 * @type string $slug Unique URL slug for the subnav item. 81 * @type string $parent_slug Slug of the top-level nav item under which the new subnav item should 82 * be added. 83 * @type string $parent_url URL of the parent nav item. 84 * @type bool|string $item_css_id Optional. 'id' attribute for the nav item. Default: the value of `$slug`. 85 * @type bool $user_has_access Optional. True if the logged-in user has access to the subnav item, 86 * otherwise false. Can be set dynamically when registering the subnav; 87 * eg, use `bp_is_my_profile()` to restrict access to profile owners only. 88 * Default: true. 89 * @type bool $site_admin_only Optional. Whether the nav item should be visible only to site admins 90 * (those with the 'bp_moderate' cap). Default: false. 91 * @type int $position Optional. Numerical index specifying where the item should appear in the 92 * subnav array. Default: 90. 93 * @type callable $screen_function The callback function that will run when the nav item is clicked. 94 * @type string $link Optional. The URL that the subnav item should point to. Defaults to a value 95 * generated from the `$parent_url` + `$slug`. 96 * @type bool $show_in_admin_bar Optional. Whether the nav item should be added into the group's "Edit" 97 * Admin Bar menu for group admins. Default: false. 98 * } 99 * @return bool|null Returns false on failure. 100 */ 101 function bp_core_new_subnav_item( $args = '' ) { 102 $e = new Exception; 103 $trace = $e->getTraceAsString(); 104 105 _deprecated_function( __FUNCTION__, '2.6', "bp_core_add_subnav_item() instead.\n===\nTrace:\n" . $trace . "\n===\n" ); 106 return bp_core_add_subnav_item( $args ); 107 } 108 109 /** 110 * Sort all subnavigation arrays. 111 * 112 * @since 1.1.0 113 * @deprecated 2.6.0 114 * 115 * @return bool|null Returns false on failure. 116 */ 117 function bp_core_sort_subnav_items() { 118 _deprecated_function( __FUNCTION__, '2.6' ); 119 } 120 121 /** 122 * Remove a nav item from the navigation array. 123 * 124 * @since 1.0.0 125 * @deprecated 2.6.0 126 * 127 * @param int $parent_id The slug of the parent navigation item. 128 * @return bool Returns false on failure, ie if the nav item can't be found. 129 */ 130 function bp_core_remove_nav_item( $parent_id ) { 131 $bp = buddypress(); 132 133 $e = new Exception; 134 $trace = $e->getTraceAsString(); 135 136 _deprecated_function( __FUNCTION__, '2.6', "bp_core_delete_nav_item() instead.\n===\nTrace:\n" . $trace . "\n===\n" ); 137 138 if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) { 139 140 if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) { 141 return bp_core_delete_nav_item( $parent_id, 'groups' ); 142 } 143 } 144 145 return bp_core_delete_nav_item( $parent_id ); 146 } 147 148 /** 149 * Remove a subnav item from the navigation array. 150 * 151 * @since 1.0.0 152 * @deprecated 2.6.0 153 * 154 * @param string $parent_id The slug of the parent navigation item. 155 * @param string $slug The slug of the subnav item to be removed. 156 */ 157 function bp_core_remove_subnav_item( $parent_id, $slug ) { 158 $bp = buddypress(); 159 160 $e = new Exception; 161 $trace = $e->getTraceAsString(); 162 163 _deprecated_function( __FUNCTION__, '2.6', "bp_core_delete_subnav_item() instead.\n===\nTrace:\n" . $trace . "\n===\n" ); 164 165 if ( bp_is_active( 'groups' ) && isset( $bp->groups->nav ) ) { 166 167 if ( $bp->groups->nav->get_primary( array( 'slug' => $parent_id ) ) ) { 168 return bp_core_delete_subnav_item( $slug, $parent_id, 'groups' ); 169 } 170 } 171 172 return bp_core_delete_subnav_item( $slug, $parent_id ); 173 } -
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() { 47 47 ) ); 48 48 49 49 // 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' ) ); 51 51 52 52 // Check if current group has Manage tabs. 53 if ( empty( $bp->bp_options_nav[ $nav_index ] )) {53 if ( ! $secondary_nav_items ) { 54 54 return; 55 55 } 56 56 57 57 // Build the Group Admin menus. 58 foreach ( $ bp->bp_options_nav[ $nav_index ]as $menu ) {58 foreach ( $secondary_nav_items as $menu ) { 59 59 /** 60 60 * Should we add the current manage link in the Group's "Edit" Admin Bar menu ? 61 61 * … … function bp_groups_group_admin_menu() { 63 63 * to also add the link to the "edit screen" of their group component. To do so, set the 64 64 * the 'show_in_admin_bar' argument of your edit screen to true 65 65 */ 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 ); 68 68 69 69 // 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 ); 72 72 } 73 73 74 74 $wp_admin_bar->add_menu( array( 75 75 'parent' => $bp->group_admin_menu_id, 76 'id' => $menu ['slug'],76 'id' => $menu->slug, 77 77 'title' => $title, 78 'href' => bp_get_groups_action_link( 'admin/' . $menu ['slug'])78 'href' => bp_get_groups_action_link( 'admin/' . $menu->slug ) 79 79 ) ); 80 80 } 81 81 } -
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 { 737 737 'screen_function' => array( &$this, '_display_hook' ), 738 738 'user_has_access' => $user_can_see_nav_item, 739 739 'no_access_url' => $group_permalink, 740 ) );740 ), 'groups' ); 741 741 } 742 742 743 743 // If the user can visit the screen, we register it. … … class BP_Group_Extension { 752 752 'screen_function' => array( &$this, '_display_hook' ), 753 753 'user_has_access' => $user_can_visit, 754 754 'no_access_url' => $group_permalink, 755 ) );755 ), 'groups' ); 756 756 757 757 // When we are viewing the extension display page, set the title and options title. 758 758 if ( bp_is_current_action( $this->slug ) ) { … … class BP_Group_Extension { 967 967 } 968 968 969 969 // Add the tab to the manage navigation. 970 bp_core_ new_subnav_item( $subnav_args);970 bp_core_add_subnav_item( $subnav_args, 'groups' ); 971 971 972 972 // Catch the edit screen and forward it to the plugin template. 973 973 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..891c90e 100644
class BP_Groups_Component extends BP_Component { 253 253 // Check once if the current group has a custom front template. 254 254 $this->current_group->front_template = bp_groups_get_front_template( $this->current_group ); 255 255 256 // Backward compatibility for plugins modifying the legacy bp_options_nav global property. 257 if ( buddypress()->do_nav_backcompat ) { 258 $bp->bp_options_nav = new BP_Core_BP_Options_Nav_BackCompat(); 259 } 260 261 // Initialize the nav for the groups component. 262 $this->nav = new BP_Core_Nav( $this->current_group->id ); 263 256 264 // Set current_group to 0 to prevent debug errors. 257 265 } else { 258 266 $this->current_group = 0; … … class BP_Groups_Component extends BP_Component { 496 504 // Reset sub nav. 497 505 $sub_nav = array(); 498 506 499 // Add 'Groups' to the main navigation. 500 $main_nav = array( 507 /** 508 * Set the Current Group's main navigation 509 * 510 * Since 2.6.0 it's now using its own navigation by passing the 511 * component's id as the second argument of bp_core_add_nav_item() 512 */ 513 bp_core_add_nav_item( array( 501 514 'name' => __( 'Memberships', 'buddypress' ), 502 515 'slug' => $this->current_group->slug, 503 516 'position' => -1, // Do not show in BuddyBar. 504 517 'screen_function' => 'groups_screen_group_home', 505 518 'default_subnav_slug' => $this->default_extension, 506 519 'item_css_id' => $this->id 507 ) ;520 ), 'groups' ); 508 521 509 522 $group_link = bp_get_group_permalink( $this->current_group ); 510 523 … … class BP_Groups_Component extends BP_Component { 675 688 ), $default_params ); 676 689 } 677 690 678 parent::setup_nav( $main_nav, $sub_nav ); 691 foreach( $sub_nav as $nav ) { 692 /** 693 * Set the Current Group's sub navigation 694 * 695 * Since 2.6.0 it's now using its own sub navigation by passing it 696 * as the second argument of bp_core_add_subnav_item() 697 */ 698 bp_core_add_subnav_item( $nav, 'groups' ); 699 } 679 700 } 680 701 681 702 if ( isset( $this->current_group->user_has_access ) ) { -
src/bp-loader.php
diff --git src/bp-loader.php src/bp-loader.php index 4a744c4..4a315b1 100644
class BuddyPress { 72 72 /** 73 73 * @var array The canonical URI stack. 74 74 * @see bp_redirect_canonical() 75 * @see bp_core_ new_nav_item()75 * @see bp_core_add_nav_item() 76 76 */ 77 77 public $canonical_stack = array(); 78 78 … … class BuddyPress { 109 109 */ 110 110 public $do_autoload = false; 111 111 112 /** 113 * Whether to load backward compatibility classes for navigation globals. 114 * 115 * @since 2.6.0 116 * @var bool 117 */ 118 public $do_nav_backcompat = false; 119 112 120 /** Option Overload *******************************************************/ 113 121 114 122 /** … … class BuddyPress { 434 442 /** Post types and taxonomies *****************************************/ 435 443 $this->email_post_type = apply_filters( 'bp_email_post_type', 'bp-email' ); 436 444 $this->email_taxonomy_type = apply_filters( 'bp_email_tax_type', 'bp-email-type' ); 445 446 /** Navigation backward compatibility *********************************/ 447 if ( interface_exists( 'ArrayAccess', false ) ) { 448 $this->do_nav_backcompat = true; 449 } 437 450 } 438 451 439 452 /** -
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() { 1290 1290 $bp = buddypress(); 1291 1291 1292 1292 // Loop through each navigation item. 1293 foreach( (array) $bp-> bp_navas $nav_item ) {1293 foreach( (array) $bp->members->nav->get_primary() as $nav_item ) { 1294 1294 1295 1295 $selected = ''; 1296 1296 1297 1297 // 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 ) { 1299 1299 $selected = ' class="current selected"'; 1300 1300 } 1301 1301 … … function bp_get_loggedin_user_nav() { 1307 1307 $selected = ''; 1308 1308 1309 1309 if ( bp_is_active( 'friends' ) ) { 1310 if ( $nav_item ['css_id']== $bp->friends->id ) {1310 if ( $nav_item->css_id == $bp->friends->id ) { 1311 1311 if ( friends_check_friendship( bp_loggedin_user_id(), bp_displayed_user_id() ) ) { 1312 1312 $selected = ' class="current selected"'; 1313 1313 } … … function bp_get_loggedin_user_nav() { 1316 1316 } 1317 1317 1318 1318 // 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 ) ); 1320 1320 } 1321 1321 1322 1322 // Always add a log out list item to the end of the navigation. … … function bp_get_loggedin_user_nav() { 1333 1333 function bp_get_displayed_user_nav() { 1334 1334 $bp = buddypress(); 1335 1335 1336 foreach ( (array) $bp->bp_navas $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() ) { 1338 1338 continue; 1339 } 1339 1340 1340 1341 $selected = ''; 1341 if ( bp_is_current_component( $user_nav_item ['slug']) ) {1342 if ( bp_is_current_component( $user_nav_item->slug ) ) { 1342 1343 $selected = ' class="current selected"'; 1343 1344 } 1344 1345 1345 1346 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 ); 1347 1348 } else { 1348 $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item ['link']);1349 $link = trailingslashit( bp_displayed_user_domain() . $user_nav_item->link ); 1349 1350 } 1350 1351 1351 1352 /** … … function bp_get_displayed_user_nav() { 1359 1360 * @param array $user_nav_item Array holding parts used to construct tab list item. 1360 1361 * Passed by reference. 1361 1362 */ 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 ) ); 1363 1364 } 1364 1365 } 1365 1366 -
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..d077b0d 100644
class BP_Members_Component extends BP_Component { 150 150 // The domain for the user currently being displayed. 151 151 $bp->displayed_user->domain = bp_core_get_user_domain( bp_displayed_user_id() ); 152 152 153 // Backward compatibility for plugins modifying the legacy bp_nav and bp_options_nav global properties. 154 if ( buddypress()->do_nav_backcompat ) { 155 $bp->bp_nav = new BP_Core_BP_Nav_BackCompat(); 156 $bp->bp_options_nav = new BP_Core_BP_Options_Nav_BackCompat(); 157 } 158 159 // Initialize the nav for the members component. 160 $this->nav = new BP_Core_Nav(); 161 153 162 /** Signup *********************************************************** 154 163 */ 155 164 -
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() { 132 132 $class = ( 0 === $count ) ? 'no-count' : 'count'; 133 133 $nav_name = sprintf( __( 'Messages <span class="%s">%s</span>', 'buddypress' ), esc_attr( $class ), bp_core_number_format( $count ) ); 134 134 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 ); 136 139 137 140 /** 138 141 * 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' ); 488 488 */ 489 489 function bp_settings_remove_email_subnav() { 490 490 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 ); 492 492 } 493 493 } 494 494 add_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 { 287 287 // Get the settings slug. 288 288 $settings_slug = bp_get_settings_slug(); 289 289 290 bp_core_ new_subnav_item( array(290 bp_core_add_subnav_item( array( 291 291 'name' => _x( 'Profile Visibility', 'Profile settings sub nav', 'buddypress' ), 292 292 'slug' => 'profile', 293 293 'parent_url' => trailingslashit( $user_domain . $settings_slug ), … … class BP_XProfile_Component extends BP_Component { 295 295 'screen_function' => 'bp_xprofile_screen_settings', 296 296 'position' => 30, 297 297 'user_has_access' => bp_core_can_edit_settings() 298 ) );298 ), 'members' ); 299 299 } 300 300 301 301 /** -
new file tests/phpunit/testcases/core/nav/globalAccess.php
diff --git tests/phpunit/testcases/core/nav/globalAccess.php tests/phpunit/testcases/core/nav/globalAccess.php new file mode 100644 index 0000000..a1dc7df
- + 1 <?php 2 3 /** 4 * @group core 5 * @group nav 6 * @ticket BP6534 7 * @expectedIncorrectUsage bp_nav 8 */ 9 class BP_Core_Nav_GlobalAccess extends BP_UnitTestCase { 10 protected $bp_nav; 11 protected $bp_options_nav; 12 13 public function setUp() { 14 parent::setUp(); 15 $this->bp_nav = buddypress()->bp_nav; 16 $this->bp_options_nav = buddypress()->bp_options_nav; 17 } 18 19 public function tearDown() { 20 buddypress()->bp_nav = $this->bp_nav; 21 buddypress()->bp_options_nav = $this->bp_options_nav; 22 parent::tearDown(); 23 } 24 25 protected function create_nav_items() { 26 $this->setExpectedDeprecated( 'bp_core_new_nav_item' ); 27 $this->setExpectedDeprecated( 'bp_core_new_subnav_item' ); 28 29 bp_core_new_nav_item( array( 30 'name' => 'Foo', 31 'slug' => 'foo', 32 'position' => 25, 33 'screen_function' => 'foo_screen_function', 34 'default_subnav_slug' => 'foo-subnav' 35 ) ); 36 37 bp_core_new_subnav_item( array( 38 'name' => 'Foo Subnav', 39 'slug' => 'foo-subnav', 40 'parent_url' => 'example.com/foo', 41 'parent_slug' => 'foo', 42 'screen_function' => 'foo_screen_function', 43 'position' => 10 44 ) ); 45 } 46 47 /** 48 * Create a group, set up nav item, and go to the group. 49 */ 50 protected function set_up_group() { 51 $g = $this->factory->group->create( array( 52 'slug' => 'testgroup', 53 ) ); 54 55 $group = groups_get_group( array( 'group_id' => $g ) ); 56 $group_permalink = bp_get_group_permalink( $group ); 57 58 $this->go_to( $group_permalink ); 59 60 // @todo There is a backward compatibility break with anyone using 61 // 'parent_slug' = group_slug to add a group subnav using 62 // `bp_core_new_subnav_item()` 63 bp_core_add_subnav_item( array( 64 'name' => 'Foo', 65 'slug' => 'foo', 66 'parent_url' => $group_permalink, 67 'parent_slug' => 'testgroup', 68 'screen_function' => 'foo_screen_function', 69 'position' => 10 70 ), 'groups' ); 71 } 72 73 public function test_bp_nav_isset() { 74 $this->create_nav_items(); 75 76 $bp = buddypress(); 77 78 $this->assertTrue( isset( $bp->bp_nav ) ); 79 $this->assertTrue( isset( $bp->bp_nav['foo'] ) ); 80 $this->assertTrue( isset( $bp->bp_nav['foo']['name'] ) ); 81 } 82 83 public function test_bp_nav_unset() { 84 $this->create_nav_items(); 85 86 $bp = buddypress(); 87 88 // No support for this - it would create a malformed nav item. 89 /* 90 unset( $bp->bp_nav['foo']['css_id'] ); 91 $this->assertFalse( isset( $bp->bp_nav['foo']['css_id'] ) ); 92 */ 93 94 unset( $bp->bp_nav['foo'] ); 95 $this->assertFalse( isset( $bp->bp_nav['foo'] ) ); 96 } 97 98 public function test_bp_nav_get() { 99 $this->create_nav_items(); 100 101 $bp = buddypress(); 102 103 $foo = $bp->bp_nav['foo']; 104 $this->assertSame( 'Foo', $foo['name'] ); 105 106 $this->assertSame( 'Foo', $bp->bp_nav['foo']['name'] ); 107 } 108 109 public function test_bp_nav_set() { 110 $this->create_nav_items(); 111 112 $bp = buddypress(); 113 114 $bp->bp_nav['foo']['name'] = 'Bar'; 115 116 $nav = bp_get_nav_menu_items(); 117 118 foreach ( $nav as $_nav ) { 119 if ( 'foo' === $_nav->css_id ) { 120 $found = $_nav; 121 break; 122 } 123 } 124 125 $this->assertSame( 'Bar', $found->name ); 126 } 127 128 public function test_bp_options_nav_isset() { 129 $this->create_nav_items(); 130 131 $bp = buddypress(); 132 133 $this->assertTrue( isset( $bp->bp_options_nav ) ); 134 $this->assertTrue( isset( $bp->bp_options_nav['foo'] ) ); 135 $this->assertTrue( isset( $bp->bp_options_nav['foo']['foo-subnav'] ) ); 136 $this->assertTrue( isset( $bp->bp_options_nav['foo']['foo-subnav']['name'] ) ); 137 } 138 139 public function test_bp_options_nav_unset() { 140 $this->create_nav_items(); 141 142 $bp = buddypress(); 143 144 // No support for this - it would create a malformed nav item. 145 /* 146 unset( $bp->bp_options_nav['foo']['foo-subnav']['user_has_access'] ); 147 $this->assertFalse( isset( $bp->bp_options_nav['foo']['foo-subnav']['user_has_access'] ) ); 148 */ 149 150 unset( $bp->bp_options_nav['foo']['foo-subnav'] ); 151 $this->assertFalse( isset( $bp->bp_options_nav['foo']['foo-subnav'] ) ); 152 153 // Make sure the parent nav hasn't been wiped out. 154 $this->assertTrue( isset( $bp->bp_options_nav['foo'] ) ); 155 156 unset( $bp->bp_options_nav['foo'] ); 157 $this->assertFalse( isset( $bp->bp_options_nav['foo'] ) ); 158 } 159 160 public function test_bp_options_nav_get() { 161 $this->create_nav_items(); 162 163 $bp = buddypress(); 164 165 $foo_subnav = $bp->bp_options_nav['foo']['foo-subnav']; 166 $this->assertSame( 'Foo Subnav', $foo_subnav['name'] ); 167 168 $this->assertSame( 'Foo Subnav', $bp->bp_options_nav['foo']['foo-subnav']['name'] ); 169 } 170 171 public function test_bp_options_nav_set() { 172 $this->create_nav_items(); 173 174 $bp = buddypress(); 175 176 $bp->bp_options_nav['foo']['foo-subnav']['name'] = 'Bar'; 177 $nav = bp_get_nav_menu_items(); 178 179 foreach ( $nav as $_nav ) { 180 if ( 'foo-subnav' === $_nav->css_id ) { 181 $found = $_nav; 182 break; 183 } 184 } 185 186 $this->assertSame( 'Bar', $found->name ); 187 188 $subnav = array( 189 'name' => 'Bar', 190 'css_id' => 'bar-id', 191 'link' => 'bar-link', 192 'slug' => 'bar-slug', 193 'user_has_access' => true, 194 ); 195 $bp->bp_options_nav['foo']['foo-subnav'] = $subnav; 196 $nav = bp_get_nav_menu_items(); 197 198 foreach ( $nav as $_nav ) { 199 if ( 'bar-id' === $_nav->css_id ) { 200 $found = $_nav; 201 break; 202 } 203 } 204 205 $this->assertSame( 'Bar', $found->name ); 206 } 207 208 /** 209 * @group groups 210 */ 211 public function test_bp_options_nav_isset_group_nav() { 212 $this->set_up_group(); 213 214 $bp = buddypress(); 215 216 $this->assertTrue( isset( $bp->bp_options_nav ) ); 217 $this->assertTrue( isset( $bp->bp_options_nav['testgroup'] ) ); 218 $this->assertTrue( isset( $bp->bp_options_nav['testgroup']['foo'] ) ); 219 $this->assertTrue( isset( $bp->bp_options_nav['testgroup']['foo']['name'] ) ); 220 } 221 222 /** 223 * @group groups 224 */ 225 public function test_bp_options_nav_unset_group_nav() { 226 $this->set_up_group(); 227 228 $bp = buddypress(); 229 230 // No support for this - it would create a malformed nav item. 231 /* 232 unset( $bp->bp_options_nav['testgroup']['foo']['user_has_access'] ); 233 $this->assertFalse( isset( $bp->bp_options_nav['testgroup']['foo']['user_has_access'] ) ); 234 */ 235 236 unset( $bp->bp_options_nav['testgroup']['foo'] ); 237 $this->assertFalse( isset( $bp->bp_options_nav['testgroup']['foo'] ) ); 238 239 unset( $bp->bp_options_nav['testgroup'] ); 240 $this->assertFalse( isset( $bp->bp_options_nav['testgroup'] ) ); 241 } 242 243 /** 244 * @group groups 245 */ 246 public function test_bp_options_nav_get_group_nav() { 247 $this->set_up_group(); 248 249 $bp = buddypress(); 250 251 $foo = $bp->bp_options_nav['testgroup']['foo']; 252 $this->assertSame( 'Foo', $foo['name'] ); 253 254 $this->assertSame( 'Foo', $bp->bp_options_nav['testgroup']['foo']['name'] ); 255 } 256 257 /** 258 * @group groups 259 */ 260 public function test_bp_options_nav_set_group_nav() { 261 $this->set_up_group(); 262 263 $bp = buddypress(); 264 265 $bp->bp_options_nav['testgroup']['foo']['name'] = 'Bar'; 266 $nav = bp_get_nav_menu_items( 'groups' ); 267 268 foreach ( $nav as $_nav ) { 269 if ( 'foo' === $_nav->css_id ) { 270 $found = $_nav; 271 break; 272 } 273 } 274 275 $this->assertSame( 'Bar', $found->name ); 276 277 $subnav = array( 278 'name' => 'Bar', 279 'css_id' => 'bar-id', 280 'link' => 'bar-link', 281 'slug' => 'bar-slug', 282 'user_has_access' => true, 283 ); 284 $bp->bp_options_nav['testgroup']['foo'] = $subnav; 285 $nav = bp_get_nav_menu_items( 'groups' ); 286 287 foreach ( $nav as $_nav ) { 288 if ( 'bar-id' === $_nav->css_id ) { 289 $found = $_nav; 290 break; 291 } 292 } 293 294 $this->assertSame( 'Bar', $found->name ); 295 } 296 }