[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Common template tags 4 * 5 * @since 3.0.0 6 * @version 8.0.0 7 */ 8 9 // Exit if accessed directly. 10 defined( 'ABSPATH' ) || exit; 11 12 /** 13 * Fire specific hooks at various places of templates 14 * 15 * @since 3.0.0 16 * 17 * @param array $pieces The list of terms of the hook to join. 18 */ 19 function bp_nouveau_hook( $pieces = array() ) { 20 if ( ! $pieces ) { 21 return; 22 } 23 24 $bp_prefix = reset( $pieces ); 25 if ( 'bp' !== $bp_prefix ) { 26 array_unshift( $pieces, 'bp' ); 27 } 28 29 $hook = join( '_', $pieces ); 30 31 /** 32 * Fires inside the `bp_nouveau_hook()` function. 33 * 34 * @since 3.0.0 35 */ 36 do_action( $hook ); 37 } 38 39 /** 40 * Fire plugin hooks in the plugins.php template (Groups and Members single items) 41 * 42 * @since 3.0.0 43 * 44 * @param string The suffix of the hook. 45 */ 46 function bp_nouveau_plugin_hook( $suffix = '' ) { 47 if ( ! $suffix ) { 48 return; 49 } 50 51 bp_nouveau_hook( 52 array( 53 'bp', 54 'template', 55 $suffix, 56 ) 57 ); 58 } 59 60 /** 61 * Fire friend hooks 62 * 63 * @todo Move this into bp-nouveau/includes/friends/template-tags.php 64 * once we'll need other friends template tags. 65 * 66 * @since 3.0.0 67 * 68 * @param string The suffix of the hook. 69 */ 70 function bp_nouveau_friend_hook( $suffix = '' ) { 71 if ( ! $suffix ) { 72 return; 73 } 74 75 bp_nouveau_hook( 76 array( 77 'bp', 78 'friend', 79 $suffix, 80 ) 81 ); 82 } 83 84 /** 85 * Add classes to style the template notice/feedback message 86 * 87 * @since 3.0.0 88 */ 89 function bp_nouveau_template_message_classes() { 90 $bp_nouveau = bp_nouveau(); 91 $classes = array( 'bp-feedback', 'bp-messages' ); 92 93 if ( ! empty( $bp_nouveau->template_message['message'] ) ) { 94 $classes[] = 'bp-template-notice'; 95 } 96 97 $classes[] = bp_nouveau_get_template_message_type(); 98 echo join( ' ', array_map( 'sanitize_html_class', $classes ) ); 99 } 100 101 /** 102 * Get the template notice/feedback message type 103 * 104 * @since 3.0.0 105 * 106 * @return string The type of the notice. Defaults to error. 107 */ 108 function bp_nouveau_get_template_message_type() { 109 $bp_nouveau = bp_nouveau(); 110 $type = 'error'; 111 112 if ( ! empty( $bp_nouveau->template_message['type'] ) ) { 113 $type = $bp_nouveau->template_message['type']; 114 } elseif ( ! empty( $bp_nouveau->user_feedback['type'] ) ) { 115 $type = $bp_nouveau->user_feedback['type']; 116 } 117 118 return $type; 119 } 120 121 /** 122 * Checks if a template notice/feedback message is set 123 * 124 * @since 3.0.0 125 * 126 * @return bool True if a template notice is set. False otherwise. 127 */ 128 function bp_nouveau_has_template_message() { 129 $bp_nouveau = bp_nouveau(); 130 131 if ( empty( $bp_nouveau->template_message['message'] ) && empty( $bp_nouveau->user_feedback ) ) { 132 return false; 133 } 134 135 return true; 136 } 137 138 /** 139 * Checks if the template notice/feedback message needs a dismiss button 140 * 141 * @todo Dismiss button re-worked to try and prevent buttons on general 142 * BP template notices - Nouveau user_feedback key needs review. 143 * 144 * @since 3.0.0 145 * 146 * @return bool True if a template notice needs a dismiss button. False otherwise. 147 */ 148 function bp_nouveau_has_dismiss_button() { 149 $bp_nouveau = bp_nouveau(); 150 151 // BP template notices - set 'dismiss' true for a type in `bp_nouveau_template_notices()` 152 if ( ! empty( $bp_nouveau->template_message['message'] ) && true === $bp_nouveau->template_message['dismiss'] ) { 153 return true; 154 } 155 156 // Test for isset as value can be falsey. 157 if ( isset( $bp_nouveau->user_feedback['dismiss'] ) ) { 158 return true; 159 } 160 161 return false; 162 } 163 164 /** 165 * Ouptut the dismiss type. 166 * 167 * $type is used to set the data-attr for the button. 168 * 'clear' is tested for & used to remove cookies, if set, in buddypress-nouveau.js. 169 * Currently template_notices(BP) will take $type = 'clear' if button set to true. 170 * 171 * @since 3.0.0 172 */ 173 function bp_nouveau_dismiss_button_type() { 174 $bp_nouveau = bp_nouveau(); 175 $type = 'clear'; 176 177 if ( ! empty( $bp_nouveau->user_feedback['dismiss'] ) ) { 178 $type = $bp_nouveau->user_feedback['dismiss']; 179 } 180 181 echo esc_attr( $type ); 182 } 183 184 /** 185 * Displays a template notice/feedback message. 186 * 187 * @since 3.0.0 188 */ 189 function bp_nouveau_template_message() { 190 echo bp_nouveau_get_template_message(); 191 } 192 193 /** 194 * Get the template notice/feedback message and make sure core filter is applied. 195 * 196 * @since 3.0.0 197 * 198 * @return string HTML Output. 199 */ 200 function bp_nouveau_get_template_message() { 201 $bp_nouveau = bp_nouveau(); 202 203 if ( ! empty( $bp_nouveau->user_feedback['message'] ) ) { 204 $user_feedback = $bp_nouveau->user_feedback['message']; 205 206 // @TODO: why is this treated differently? 207 foreach ( array( 'wp_kses_data', 'wp_unslash', 'wptexturize', 'convert_smilies', 'convert_chars' ) as $filter ) { 208 $user_feedback = call_user_func( $filter, $user_feedback ); 209 } 210 211 return '<p>' . $user_feedback . '</p>'; 212 213 } elseif ( ! empty( $bp_nouveau->template_message['message'] ) ) { 214 /** 215 * Filters the 'template_notices' feedback message content. 216 * 217 * @since 1.5.5 218 * 219 * @param string $template_message Feedback message content. 220 * @param string $type The type of message being displayed. 221 * Either 'updated' or 'error'. 222 */ 223 return apply_filters( 'bp_core_render_message_content', $bp_nouveau->template_message['message'], bp_nouveau_get_template_message_type() ); 224 } 225 } 226 227 /** 228 * Template tag to display feedback notices to users, if there are to display 229 * 230 * @since 3.0.0 231 */ 232 function bp_nouveau_template_notices() { 233 $bp = buddypress(); 234 $bp_nouveau = bp_nouveau(); 235 236 if ( ! empty( $bp->template_message ) ) { 237 // Clone BuddyPress template message to avoid altering it. 238 $template_message = array( 'message' => $bp->template_message ); 239 240 if ( ! empty( $bp->template_message_type ) ) { 241 $template_message['type'] = $bp->template_message_type; 242 } 243 244 // Adds a 'dimiss' (button) key to array - set true/false. 245 $template_message['dismiss'] = false; 246 247 // Set dismiss button true for sitewide notices 248 if ( 'bp-sitewide-notice' == $template_message['type'] ) { 249 $template_message['dismiss'] = true; 250 } 251 252 $bp_nouveau->template_message = $template_message; 253 bp_get_template_part( 'common/notices/template-notices' ); 254 255 // Reset just after rendering it. 256 $bp_nouveau->template_message = array(); 257 258 /** 259 * Fires after the display of any template_notices feedback messages. 260 * 261 * @since 3.0.0 262 */ 263 do_action( 'bp_core_render_message' ); 264 } 265 266 /** 267 * Fires towards the top of template pages for notice display. 268 * 269 * @since 3.0.0 270 */ 271 do_action( 'template_notices' ); 272 } 273 274 /** 275 * Displays a feedback message to the user. 276 * 277 * @since 3.0.0 278 * 279 * @param string $feedback_id The ID of the message to display 280 */ 281 function bp_nouveau_user_feedback( $feedback_id = '' ) { 282 if ( ! isset( $feedback_id ) ) { 283 return; 284 } 285 286 $bp_nouveau = bp_nouveau(); 287 $feedback = bp_nouveau_get_user_feedback( $feedback_id ); 288 289 if ( ! $feedback ) { 290 return; 291 } 292 293 if ( ! empty( $feedback['before'] ) ) { 294 295 /** 296 * Fires before display of a feedback message to the user. 297 * 298 * This is a dynamic filter that is dependent on the "before" value provided by bp_nouveau_get_user_feedback(). 299 * 300 * @since 3.0.0 301 */ 302 do_action( $feedback['before'] ); 303 } 304 305 $bp_nouveau->user_feedback = $feedback; 306 307 bp_get_template_part( 308 309 /** 310 * Filter here if you wish to use a different templates than the notice one. 311 * 312 * @since 3.0.0 313 * 314 * @param string path to your template part. 315 */ 316 apply_filters( 'bp_nouveau_user_feedback_template', 'common/notices/template-notices' ) 317 ); 318 319 if ( ! empty( $feedback['after'] ) ) { 320 321 /** 322 * Fires before display of a feedback message to the user. 323 * 324 * This is a dynamic filter that is dependent on the "after" value provided by bp_nouveau_get_user_feedback(). 325 * 326 * @since 3.0.0 327 */ 328 do_action( $feedback['after'] ); 329 } 330 331 // Reset the feedback message. 332 $bp_nouveau->user_feedback = array(); 333 } 334 335 /** 336 * Template tag to wrap the before component loop 337 * 338 * @since 3.0.0 339 */ 340 function bp_nouveau_before_loop() { 341 $component = bp_current_component(); 342 343 if ( bp_is_group() ) { 344 $component = bp_current_action(); 345 } 346 347 /** 348 * Fires before the start of the component loop. 349 * 350 * This is a variable hook that is dependent on the current component. 351 * 352 * @since 1.2.0 353 */ 354 do_action( "bp_before_{$component}_loop" ); 355 } 356 357 /** 358 * Template tag to wrap the after component loop 359 * 360 * @since 3.0.0 361 */ 362 function bp_nouveau_after_loop() { 363 $component = bp_current_component(); 364 365 if ( bp_is_group() ) { 366 $component = bp_current_action(); 367 } 368 369 /** 370 * Fires after the finish of the component loop. 371 * 372 * This is a variable hook that is dependent on the current component. 373 * 374 * @since 1.2.0 375 */ 376 do_action( "bp_after_{$component}_loop" ); 377 } 378 379 /** 380 * Pagination for loops 381 * 382 * @param string $position 383 * 384 * @since 3.0.0 385 */ 386 function bp_nouveau_pagination( $position ) { 387 $screen = 'dir'; 388 $pagination_type = bp_current_component(); 389 390 if ( bp_is_user() ) { 391 $screen = 'user'; 392 393 } elseif ( bp_is_group() ) { 394 $screen = 'group'; 395 $pagination_type = bp_current_action(); 396 397 if ( bp_is_group_admin_page() ) { 398 $pagination_type = bp_action_variable( 0 ); 399 } 400 } 401 402 switch ( $pagination_type ) { 403 case 'blogs': 404 $pag_count = bp_get_blogs_pagination_count(); 405 $pag_links = bp_get_blogs_pagination_links(); 406 $top_hook = 'bp_before_directory_blogs_list'; 407 $bottom_hook = 'bp_after_directory_blogs_list'; 408 $page_arg = $GLOBALS['blogs_template']->pag_arg; 409 break; 410 411 case 'members': 412 case 'friends': 413 case 'manage-members': 414 $pag_count = bp_get_members_pagination_count(); 415 $pag_links = bp_get_members_pagination_links(); 416 417 // Groups single items are not using these hooks 418 if ( ! bp_is_group() ) { 419 $top_hook = 'bp_before_directory_members_list'; 420 $bottom_hook = 'bp_after_directory_members_list'; 421 } 422 423 $page_arg = $GLOBALS['members_template']->pag_arg; 424 break; 425 426 case 'groups': 427 $pag_count = bp_get_groups_pagination_count(); 428 $pag_links = bp_get_groups_pagination_links(); 429 $top_hook = 'bp_before_directory_groups_list'; 430 $bottom_hook = 'bp_after_directory_groups_list'; 431 $page_arg = $GLOBALS['groups_template']->pag_arg; 432 break; 433 434 case 'notifications': 435 $pag_count = bp_get_notifications_pagination_count(); 436 $pag_links = bp_get_notifications_pagination_links(); 437 $top_hook = ''; 438 $bottom_hook = ''; 439 $page_arg = buddypress()->notifications->query_loop->pag_arg; 440 break; 441 442 case 'membership-requests': 443 $pag_count = bp_get_group_requests_pagination_count(); 444 $pag_links = bp_get_group_requests_pagination_links(); 445 $top_hook = ''; 446 $bottom_hook = ''; 447 $page_arg = $GLOBALS['requests_template']->pag_arg; 448 break; 449 450 default: 451 /** 452 * Use this filter to define your custom pagination parameters. 453 * 454 * @since 6.0.0 455 * 456 * @param array $value { 457 * An associative array of pagination parameters. 458 * @type string $pag_count Information about the pagination count. 459 * eg: "Viewing 1 - 10 of 20 items". 460 * @type string $pag_links The Pagination links. 461 * @type string $page_arg The argument to use to pass the page number. 462 * } 463 * @param string $pagination_type Information about the pagination type. 464 */ 465 $pagination_params = apply_filters( 'bp_nouveau_pagination_params', 466 array( 467 'pag_count' => '', 468 'pag_links' => '', 469 'page_arg' => '', 470 ), 471 $pagination_type 472 ); 473 474 list( $pag_count, $pag_links, $page_arg ) = array_values( $pagination_params ); 475 break; 476 } 477 478 $count_class = sprintf( '%1$s-%2$s-count-%3$s', $pagination_type, $screen, $position ); 479 $links_class = sprintf( '%1$s-%2$s-links-%3$s', $pagination_type, $screen, $position ); 480 ?> 481 482 <?php 483 if ( 'bottom' === $position && isset( $bottom_hook ) ) { 484 /** 485 * Fires after the component directory list. 486 * 487 * @since 3.0.0 488 */ 489 do_action( $bottom_hook ); 490 }; 491 ?> 492 493 <div class="<?php echo esc_attr( 'bp-pagination ' . sanitize_html_class( $position ) ); ?>" data-bp-pagination="<?php echo esc_attr( $page_arg ); ?>"> 494 495 <?php if ( $pag_count ) : ?> 496 <div class="<?php echo esc_attr( 'pag-count ' . sanitize_html_class( $position ) ); ?>"> 497 498 <p class="pag-data"> 499 <?php echo esc_html( $pag_count ); ?> 500 </p> 501 502 </div> 503 <?php endif; ?> 504 505 <?php if ( $pag_links ) : ?> 506 <div class="<?php echo esc_attr( 'bp-pagination-links ' . sanitize_html_class( $position ) ); ?>"> 507 508 <p class="pag-data"> 509 <?php echo wp_kses_post( $pag_links ); ?> 510 </p> 511 512 </div> 513 <?php endif; ?> 514 515 </div> 516 517 <?php 518 if ( 'top' === $position && isset( $top_hook ) ) { 519 /** 520 * Fires before the component directory list. 521 * 522 * @since 3.0.0 523 */ 524 do_action( $top_hook ); 525 }; 526 } 527 528 /** 529 * Display the component's loop classes 530 * 531 * @since 3.0.0 532 * 533 * @return string CSS class attributes (escaped). 534 */ 535 function bp_nouveau_loop_classes() { 536 echo esc_attr( bp_nouveau_get_loop_classes() ); 537 } 538 539 /** 540 * Get the component's loop classes 541 * 542 * @since 3.0.0 543 * 544 * @return string space separated value of classes. 545 */ 546 function bp_nouveau_get_loop_classes() { 547 $bp_nouveau = bp_nouveau(); 548 549 // @todo: this function could do with passing args so we can pass simple strings in or array of strings 550 $is_directory = bp_is_directory(); 551 552 // The $component is faked if it's the single group member loop 553 if ( ! $is_directory && ( bp_is_group() && 'members' === bp_current_action() ) ) { 554 $component = 'members_group'; 555 } elseif ( ! $is_directory && ( bp_is_user() && 'my-friends' === bp_current_action() ) ) { 556 $component = 'members_friends'; 557 } else { 558 $component = sanitize_key( bp_current_component() ); 559 } 560 561 /* 562 * For the groups component, we need to take in account the 563 * Groups directory can list Groups according to a Group Type. 564 */ 565 if ( 'groups' === $component ) { 566 $is_directory = bp_is_groups_directory(); 567 } 568 569 $classes = array( 570 'item-list', 571 sprintf( '%s-list', str_replace( '_', '-', $component ) ), 572 'bp-list', 573 ); 574 575 if ( bp_is_user() && 'my-friends' === bp_current_action() ) { 576 $classes[] = 'members-list'; 577 } 578 579 if ( bp_is_user() && 'requests' === bp_current_action() ) { 580 $classes[] = 'friends-request-list'; 581 } 582 583 $available_components = array( 584 'members' => true, 585 'groups' => true, 586 'blogs' => true, 587 588 /* 589 * Technically not a component but allows us to check the single group members loop as a seperate loop. 590 */ 591 'members_group' => true, 592 'members_friends' => true, 593 ); 594 595 // Only the available components supports custom layouts. 596 if ( ! empty( $available_components[ $component ] ) && ( $is_directory || bp_is_group() || bp_is_user() ) ) { 597 $customizer_option = sprintf( '%s_layout', $component ); 598 $layout_prefs = bp_nouveau_get_temporary_setting( 599 $customizer_option, 600 bp_nouveau_get_appearance_settings( $customizer_option ) 601 ); 602 603 if ( $layout_prefs && (int) $layout_prefs > 1 ) { 604 $grid_classes = bp_nouveau_customizer_grid_choices( 'classes' ); 605 606 if ( isset( $grid_classes[ $layout_prefs ] ) ) { 607 $classes = array_merge( $classes, array( 608 'grid', 609 $grid_classes[ $layout_prefs ], 610 ) ); 611 } 612 613 if ( ! isset( $bp_nouveau->{$component} ) ) { 614 $bp_nouveau->{$component} = new stdClass; 615 } 616 617 // Set the global for a later use. 618 $bp_nouveau->{$component}->loop_layout = $layout_prefs; 619 } 620 } 621 622 /** 623 * Filter to edit/add classes. 624 * 625 * NB: you can also directly add classes into the template parts. 626 * 627 * @since 3.0.0 628 * 629 * @param array $classes The list of classes. 630 * @param string $component The current component's loop. 631 */ 632 $class_list = (array) apply_filters( 'bp_nouveau_get_loop_classes', $classes, $component ); 633 634 return join( ' ', array_map( 'sanitize_html_class', $class_list ) ); 635 } 636 637 638 /** 639 * Checks if the layout preferences is set to grid (2 or more columns). 640 * 641 * @since 3.0.0 642 * 643 * @return bool True if loop is displayed in grid mod. False otherwise. 644 */ 645 function bp_nouveau_loop_is_grid() { 646 $bp_nouveau = bp_nouveau(); 647 $component = sanitize_key( bp_current_component() ); 648 649 return ! empty( $bp_nouveau->{$component}->loop_layout ) && $bp_nouveau->{$component}->loop_layout > 1; 650 } 651 652 /** 653 * Returns the number of columns of the layout preferences. 654 * 655 * @since 3.0.0 656 * 657 * @return int The number of columns. 658 */ 659 function bp_nouveau_loop_get_grid_columns() { 660 $bp_nouveau = bp_nouveau(); 661 $component = sanitize_key( bp_current_component() ); 662 663 $columns = 1; 664 665 if ( ! empty( $bp_nouveau->{$component}->loop_layout ) ) { 666 $columns = (int) $bp_nouveau->{$component}->loop_layout; 667 } 668 669 /** 670 * Filter number of columns for this grid. 671 * 672 * @since 3.0.0 673 * 674 * @param int $columns The number of columns. 675 */ 676 return (int) apply_filters( 'bp_nouveau_loop_get_grid_columns', $columns ); 677 } 678 679 /** 680 * Return a bool check for component directory layout. 681 * 682 * Checks if activity, members, groups, blogs has the vert nav layout selected. 683 * 684 * @since 3.0.0 685 * 686 * @return bool 687 */ 688 function bp_dir_is_vert_layout() { 689 $bp_nouveau = bp_nouveau(); 690 $component = sanitize_key( bp_current_component() ); 691 692 return (bool) $bp_nouveau->{$component}->directory_vertical_layout; 693 } 694 695 /** 696 * Template tag to wrap the Legacy actions that was used 697 * after the components directory page. 698 * 699 * @since 6.0.0 700 */ 701 function bp_nouveau_after_directory_page() { 702 $component = bp_current_component(); 703 704 /** 705 * Fires at the bottom of the activity, members, groups and blogs directory template file. 706 * 707 * @since 1.5.0 Added to the members, groups directory template file. 708 * @since 2.3.0 Added to the blogs directory template file. 709 * @since 6.0.0 Added to the activity directory template file. 710 */ 711 do_action( "bp_after_directory_{$component}_page" ); 712 } 713 714 /** 715 * Get the full size avatar args. 716 * 717 * @since 3.0.0 718 * 719 * @return array The avatar arguments. 720 */ 721 function bp_nouveau_avatar_args() { 722 /** 723 * Filter arguments for full-size avatars. 724 * 725 * @since 3.0.0 726 * 727 * @param array $args { 728 * @param string $type Avatar type. 729 * @param int $width Avatar width value. 730 * @param int $height Avatar height value. 731 * } 732 */ 733 return apply_filters( 'bp_nouveau_avatar_args', array( 734 'type' => 'full', 735 'width' => bp_core_avatar_full_width(), 736 'height' => bp_core_avatar_full_height(), 737 ) ); 738 } 739 740 741 /** Template Tags for BuddyPress navigations **********************************/ 742 743 /* 744 * This is the BP Nouveau Navigation Loop. 745 * 746 * It can be used by any object using the 747 * BP_Core_Nav API introduced in BuddyPress 2.6.0. 748 */ 749 750 /** 751 * Init the Navigation Loop and check it has items. 752 * 753 * @since 3.0.0 754 * 755 * @param array $args { 756 * Array of arguments. 757 * 758 * @type string $type The type of Nav to get (primary or secondary) 759 * Default 'primary'. Required. 760 * @type string $object The object to get the nav for (eg: 'directory', 'group_manage', 761 * or any custom object). Default ''. Optional 762 * @type bool $user_has_access Used by the secondary member's & group's nav. Default true. Optional. 763 * @type bool $show_for_displayed_user Used by the primary member's nav. Default true. Optional. 764 * } 765 * 766 * @return bool True if the Nav contains items. False otherwise. 767 */ 768 function bp_nouveau_has_nav( $args = array() ) { 769 $bp_nouveau = bp_nouveau(); 770 771 $n = bp_parse_args( 772 $args, 773 array( 774 'type' => 'primary', 775 'object' => '', 776 'user_has_access' => true, 777 'show_for_displayed_user' => true, 778 ), 779 'nouveau_has_nav' 780 ); 781 782 if ( empty( $n['type'] ) ) { 783 return false; 784 } 785 786 $nav = array(); 787 $bp_nouveau->displayed_nav = ''; 788 $bp_nouveau->object_nav = $n['object']; 789 790 if ( bp_is_directory() || 'directory' === $bp_nouveau->object_nav ) { 791 $bp_nouveau->displayed_nav = 'directory'; 792 $nav = $bp_nouveau->directory_nav->get_primary(); 793 794 // So far it's only possible to build a Group nav when displaying it. 795 } elseif ( bp_is_group() ) { 796 $bp_nouveau->displayed_nav = 'groups'; 797 $parent_slug = bp_get_current_group_slug(); 798 $group_nav = buddypress()->groups->nav; 799 800 if ( 'group_manage' === $bp_nouveau->object_nav && bp_is_group_admin_page() ) { 801 $parent_slug .= '_manage'; 802 803 /** 804 * If it's not the Admin tabs, reorder the Group's nav according to the 805 * customizer setting. 806 */ 807 } else { 808 bp_nouveau_set_nav_item_order( $group_nav, bp_nouveau_get_appearance_settings( 'group_nav_order' ), $parent_slug ); 809 } 810 811 $nav = $group_nav->get_secondary( 812 array( 813 'parent_slug' => $parent_slug, 814 'user_has_access' => (bool) $n['user_has_access'], 815 ) 816 ); 817 818 // Build the nav for the displayed user 819 } elseif ( bp_is_user() ) { 820 $bp_nouveau->displayed_nav = 'personal'; 821 $user_nav = buddypress()->members->nav; 822 823 if ( 'secondary' === $n['type'] ) { 824 $nav = $user_nav->get_secondary( 825 array( 826 'parent_slug' => bp_current_component(), 827 'user_has_access' => (bool) $n['user_has_access'], 828 ) 829 ); 830 831 } else { 832 $args = array(); 833 834 if ( true === (bool) $n['show_for_displayed_user'] && ! bp_is_my_profile() ) { 835 $args = array( 'show_for_displayed_user' => true ); 836 } 837 838 // Reorder the user's primary nav according to the customizer setting. 839 bp_nouveau_set_nav_item_order( $user_nav, bp_nouveau_get_appearance_settings( 'user_nav_order' ) ); 840 841 $nav = $user_nav->get_primary( $args ); 842 } 843 844 } elseif ( ! empty( $bp_nouveau->object_nav ) ) { 845 $bp_nouveau->displayed_nav = $bp_nouveau->object_nav; 846 847 /** 848 * Use the filter to use your specific Navigation. 849 * Use the $n param to check for your custom object. 850 * 851 * @since 3.0.0 852 * 853 * @param array $nav The list of item navigations generated by the BP_Core_Nav API. 854 * @param array $n The arguments of the Navigation loop. 855 */ 856 $nav = apply_filters( 'bp_nouveau_get_nav', $nav, $n ); 857 858 } 859 860 // The navigation can be empty. 861 if ( $nav === false ) { 862 $nav = array(); 863 } 864 865 $bp_nouveau->sorted_nav = array_values( $nav ); 866 867 if ( 0 === count( $bp_nouveau->sorted_nav ) || ! $bp_nouveau->displayed_nav ) { 868 unset( $bp_nouveau->sorted_nav, $bp_nouveau->displayed_nav, $bp_nouveau->object_nav ); 869 870 return false; 871 } 872 873 $bp_nouveau->current_nav_index = 0; 874 return true; 875 } 876 877 /** 878 * Checks there are still nav items to display. 879 * 880 * @since 3.0.0 881 * 882 * @return bool True if there are still items to display. False otherwise. 883 */ 884 function bp_nouveau_nav_items() { 885 $bp_nouveau = bp_nouveau(); 886 887 if ( isset( $bp_nouveau->sorted_nav[ $bp_nouveau->current_nav_index ] ) ) { 888 return true; 889 } 890 891 $bp_nouveau->current_nav_index = 0; 892 unset( $bp_nouveau->current_nav_item ); 893 894 return false; 895 } 896 897 /** 898 * Sets the current nav item and prepare the navigation loop to iterate to next one. 899 * 900 * @since 3.0.0 901 */ 902 function bp_nouveau_nav_item() { 903 $bp_nouveau = bp_nouveau(); 904 905 $bp_nouveau->current_nav_item = $bp_nouveau->sorted_nav[ $bp_nouveau->current_nav_index ]; 906 $bp_nouveau->current_nav_index += 1; 907 } 908 909 /** 910 * Displays the nav item ID. 911 * 912 * @since 3.0.0 913 */ 914 function bp_nouveau_nav_id() { 915 echo esc_attr( bp_nouveau_get_nav_id() ); 916 } 917 918 /** 919 * Retrieve the ID attribute of the current nav item. 920 * 921 * @since 3.0.0 922 * 923 * @return string the ID attribute. 924 */ 925 function bp_nouveau_get_nav_id() { 926 $bp_nouveau = bp_nouveau(); 927 $nav_item = $bp_nouveau->current_nav_item; 928 929 if ( 'directory' === $bp_nouveau->displayed_nav ) { 930 $id = sprintf( '%1$s-%2$s', $nav_item->component, $nav_item->slug ); 931 } elseif ( 'groups' === $bp_nouveau->displayed_nav || 'personal' === $bp_nouveau->displayed_nav ) { 932 $id = sprintf( '%1$s-%2$s-li', $nav_item->css_id, $bp_nouveau->displayed_nav ); 933 } else { 934 $id = $nav_item->slug; 935 } 936 937 /** 938 * Filter to edit the ID attribute of the nav. 939 * 940 * @since 3.0.0 941 * 942 * @param string $id The ID attribute of the nav. 943 * @param object $nav_item The current nav item object. 944 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 945 */ 946 return apply_filters( 'bp_nouveau_get_nav_id', $id, $nav_item, $bp_nouveau->displayed_nav ); 947 } 948 949 /** 950 * Displays the nav item classes. 951 * 952 * @since 3.0.0 953 */ 954 function bp_nouveau_nav_classes() { 955 echo esc_attr( bp_nouveau_get_nav_classes() ); 956 } 957 958 /** 959 * Retrieve a space separated list of classes for the current nav item. 960 * 961 * @since 3.0.0 962 * 963 * @return string List of classes. 964 */ 965 function bp_nouveau_get_nav_classes() { 966 $bp_nouveau = bp_nouveau(); 967 $nav_item = $bp_nouveau->current_nav_item; 968 $classes = array(); 969 970 if ( 'directory' === $bp_nouveau->displayed_nav ) { 971 if ( ! empty( $nav_item->li_class ) ) { 972 $classes = (array) $nav_item->li_class; 973 } 974 975 if ( bp_get_current_member_type() || ( bp_is_groups_directory() && bp_get_current_group_directory_type() ) ) { 976 $classes[] = 'no-ajax'; 977 } 978 } elseif ( 'groups' === $bp_nouveau->displayed_nav || 'personal' === $bp_nouveau->displayed_nav ) { 979 $classes = array( 'bp-' . $bp_nouveau->displayed_nav . '-tab' ); 980 $selected = bp_current_action(); 981 982 // User's primary nav 983 if ( ! empty( $nav_item->primary ) ) { 984 $selected = bp_current_component(); 985 986 // Group Admin Tabs. 987 } elseif ( 'group_manage' === $bp_nouveau->object_nav ) { 988 $selected = bp_action_variable( 0 ); 989 $classes = array( 'bp-' . $bp_nouveau->displayed_nav . '-admin-tab' ); 990 991 // If we are here, it's the member's subnav 992 } elseif ( 'personal' === $bp_nouveau->displayed_nav ) { 993 $classes = array( 'bp-' . $bp_nouveau->displayed_nav . '-sub-tab' ); 994 } 995 996 if ( $nav_item->slug === $selected ) { 997 $classes = array_merge( $classes, array( 'current', 'selected' ) ); 998 } 999 } 1000 1001 if ( ! empty( $classes ) ) { 1002 $classes = array_map( 'sanitize_html_class', $classes ); 1003 } 1004 1005 /** 1006 * Filter to edit/add classes. 1007 * 1008 * NB: you can also directly add classes into the template parts. 1009 * 1010 * @since 3.0.0 1011 * 1012 * @param string $value A space separated list of classes. 1013 * @param array $classes The list of classes. 1014 * @param object $nav_item The current nav item object. 1015 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1016 */ 1017 $classes_list = apply_filters( 'bp_nouveau_get_classes', join( ' ', $classes ), $classes, $nav_item, $bp_nouveau->displayed_nav ); 1018 if ( ! $classes_list ) { 1019 $classes_list = ''; 1020 } 1021 1022 return $classes_list; 1023 } 1024 1025 /** 1026 * Displays the nav item scope. 1027 * 1028 * @since 3.0.0 1029 */ 1030 function bp_nouveau_nav_scope() { 1031 echo bp_nouveau_get_nav_scope(); // Escaped by bp_get_form_field_attributes(). 1032 } 1033 1034 /** 1035 * Retrieve the specific scope for the current nav item. 1036 * 1037 * @since 3.0.0 1038 * 1039 * @return string the specific scope of the nav. 1040 */ 1041 function bp_nouveau_get_nav_scope() { 1042 $bp_nouveau = bp_nouveau(); 1043 $nav_item = $bp_nouveau->current_nav_item; 1044 $scope = array(); 1045 1046 if ( 'directory' === $bp_nouveau->displayed_nav ) { 1047 $scope = array( 'data-bp-scope' => $nav_item->slug ); 1048 1049 } elseif ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->secondary ) ) { 1050 $scope = array( 'data-bp-user-scope' => $nav_item->slug ); 1051 1052 } else { 1053 /** 1054 * Filter to add your own scope. 1055 * 1056 * @since 3.0.0 1057 * 1058 * @param array $scope Contains the key and the value for your scope. 1059 * @param object $nav_item The current nav item object. 1060 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1061 */ 1062 $scope = apply_filters( 'bp_nouveau_set_nav_scope', $scope, $nav_item, $bp_nouveau->displayed_nav ); 1063 } 1064 1065 if ( ! $scope ) { 1066 return ''; 1067 } 1068 1069 return bp_get_form_field_attributes( 'scope', $scope ); 1070 } 1071 1072 /** 1073 * Displays the nav item URL. 1074 * 1075 * @since 3.0.0 1076 */ 1077 function bp_nouveau_nav_link() { 1078 echo esc_url( bp_nouveau_get_nav_link() ); 1079 } 1080 1081 /** 1082 * Retrieve the URL for the current nav item. 1083 * 1084 * @since 3.0.0 1085 * 1086 * @return string The URL for the nav item. 1087 */ 1088 function bp_nouveau_get_nav_link() { 1089 $bp_nouveau = bp_nouveau(); 1090 $nav_item = $bp_nouveau->current_nav_item; 1091 1092 $link = '#'; 1093 if ( ! empty( $nav_item->link ) ) { 1094 $link = $nav_item->link; 1095 } 1096 1097 if ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->primary ) ) { 1098 if ( bp_loggedin_user_domain() ) { 1099 $link = str_replace( bp_loggedin_user_domain(), bp_displayed_user_domain(), $link ); 1100 } else { 1101 $link = trailingslashit( bp_displayed_user_domain() . $link ); 1102 } 1103 } 1104 1105 /** 1106 * Filter to edit the URL of the nav item. 1107 * 1108 * @since 3.0.0 1109 * 1110 * @param string $link The URL for the nav item. 1111 * @param object $nav_item The current nav item object. 1112 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1113 */ 1114 return apply_filters( 'bp_nouveau_get_nav_link', $link, $nav_item, $bp_nouveau->displayed_nav ); 1115 } 1116 1117 /** 1118 * Displays the nav item link ID. 1119 * 1120 * @since 3.0.0 1121 */ 1122 function bp_nouveau_nav_link_id() { 1123 echo esc_attr( bp_nouveau_get_nav_link_id() ); 1124 } 1125 1126 /** 1127 * Retrieve the id attribute of the link for the current nav item. 1128 * 1129 * @since 3.0.0 1130 * 1131 * @return string The link id for the nav item. 1132 */ 1133 function bp_nouveau_get_nav_link_id() { 1134 $bp_nouveau = bp_nouveau(); 1135 $nav_item = $bp_nouveau->current_nav_item; 1136 $link_id = ''; 1137 1138 if ( ( 'groups' === $bp_nouveau->displayed_nav || 'personal' === $bp_nouveau->displayed_nav ) && ! empty( $nav_item->css_id ) ) { 1139 $link_id = $nav_item->css_id; 1140 1141 if ( ! empty( $nav_item->primary ) && 'personal' === $bp_nouveau->displayed_nav ) { 1142 $link_id = 'user-' . $link_id; 1143 } 1144 } else { 1145 $link_id = $nav_item->slug; 1146 } 1147 1148 /** 1149 * Filter to edit the link id attribute of the nav. 1150 * 1151 * @since 3.0.0 1152 * 1153 * @param string $link_id The link id attribute for the nav item. 1154 * @param object $nav_item The current nav item object. 1155 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1156 */ 1157 return apply_filters( 'bp_nouveau_get_nav_link_id', $link_id, $nav_item, $bp_nouveau->displayed_nav ); 1158 } 1159 1160 /** 1161 * Displays the nav item link title. 1162 * 1163 * @since 3.0.0 1164 */ 1165 function bp_nouveau_nav_link_title() { 1166 echo esc_attr( bp_nouveau_get_nav_link_title() ); 1167 } 1168 1169 /** 1170 * Retrieve the title attribute of the link for the current nav item. 1171 * 1172 * @since 3.0.0 1173 * 1174 * @return string The link title for the nav item. 1175 */ 1176 function bp_nouveau_get_nav_link_title() { 1177 $bp_nouveau = bp_nouveau(); 1178 $nav_item = $bp_nouveau->current_nav_item; 1179 $title = ''; 1180 1181 if ( 'directory' === $bp_nouveau->displayed_nav && ! empty( $nav_item->title ) ) { 1182 $title = $nav_item->title; 1183 1184 } elseif ( 1185 ( 'groups' === $bp_nouveau->displayed_nav || 'personal' === $bp_nouveau->displayed_nav ) 1186 && 1187 ! empty( $nav_item->name ) 1188 ) { 1189 $title = $nav_item->name; 1190 } 1191 1192 /** 1193 * Filter to edit the link title attribute of the nav. 1194 * 1195 * @since 3.0.0 1196 * 1197 * @param string $title The link title attribute for the nav item. 1198 * @param object $nav_item The current nav item object. 1199 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1200 */ 1201 return apply_filters( 'bp_nouveau_get_nav_link_title', $title, $nav_item, $bp_nouveau->displayed_nav ); 1202 } 1203 1204 /** 1205 * Displays the nav item link html text. 1206 * 1207 * @since 3.0.0 1208 */ 1209 function bp_nouveau_nav_link_text() { 1210 echo esc_html( bp_nouveau_get_nav_link_text() ); 1211 } 1212 1213 /** 1214 * Retrieve the html text of the link for the current nav item. 1215 * 1216 * @since 3.0.0 1217 * 1218 * @return string The html text for the nav item. 1219 */ 1220 function bp_nouveau_get_nav_link_text() { 1221 $bp_nouveau = bp_nouveau(); 1222 $nav_item = $bp_nouveau->current_nav_item; 1223 $link_text = ''; 1224 1225 if ( 'directory' === $bp_nouveau->displayed_nav && ! empty( $nav_item->text ) ) { 1226 $link_text = _bp_strip_spans_from_title( $nav_item->text ); 1227 1228 } elseif ( 1229 ( 'groups' === $bp_nouveau->displayed_nav || 'personal' === $bp_nouveau->displayed_nav ) 1230 && 1231 ! empty( $nav_item->name ) 1232 ) { 1233 $link_text = _bp_strip_spans_from_title( $nav_item->name ); 1234 } 1235 1236 /** 1237 * Filter to edit the html text of the nav. 1238 * 1239 * @since 3.0.0 1240 * 1241 * @param string $link_text The html text of the nav item. 1242 * @param object $nav_item The current nav item object. 1243 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1244 */ 1245 return apply_filters( 'bp_nouveau_get_nav_link_text', $link_text, $nav_item, $bp_nouveau->displayed_nav ); 1246 } 1247 1248 /** 1249 * Checks if the nav item has a count attribute. 1250 * 1251 * @since 3.0.0 1252 * 1253 * @return bool 1254 */ 1255 function bp_nouveau_nav_has_count() { 1256 $bp_nouveau = bp_nouveau(); 1257 $nav_item = $bp_nouveau->current_nav_item; 1258 $count = false; 1259 1260 if ( 'directory' === $bp_nouveau->displayed_nav ) { 1261 $count = $nav_item->count; 1262 } elseif ( 'groups' === $bp_nouveau->displayed_nav && 'members' === $nav_item->slug ) { 1263 $count = 0 !== (int) groups_get_current_group()->total_member_count; 1264 } elseif ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->primary ) ) { 1265 $count = (bool) strpos( $nav_item->name, '="count"' ); 1266 } 1267 1268 /** 1269 * Filter to edit whether the nav has a count attribute. 1270 * 1271 * @since 3.0.0 1272 * 1273 * @param bool $value True if the nav has a count attribute. False otherwise 1274 * @param object $nav_item The current nav item object. 1275 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1276 */ 1277 return (bool) apply_filters( 'bp_nouveau_nav_has_count', false !== $count, $nav_item, $bp_nouveau->displayed_nav ); 1278 } 1279 1280 /** 1281 * Displays the nav item count attribute. 1282 * 1283 * @since 3.0.0 1284 */ 1285 function bp_nouveau_nav_count() { 1286 echo esc_html( number_format_i18n( bp_nouveau_get_nav_count() ) ); 1287 } 1288 1289 /** 1290 * Retrieve the count attribute for the current nav item. 1291 * 1292 * @since 3.0.0 1293 * 1294 * @return int The count attribute for the nav item. 1295 */ 1296 function bp_nouveau_get_nav_count() { 1297 $bp_nouveau = bp_nouveau(); 1298 $nav_item = $bp_nouveau->current_nav_item; 1299 $count = 0; 1300 1301 if ( 'directory' === $bp_nouveau->displayed_nav ) { 1302 $count = (int) $nav_item->count; 1303 1304 } elseif ( 'groups' === $bp_nouveau->displayed_nav && 'members' === $nav_item->slug ) { 1305 $count = groups_get_current_group()->total_member_count; 1306 1307 // @todo imho BuddyPress shouldn't add html tags inside Nav attributes... 1308 } elseif ( 'personal' === $bp_nouveau->displayed_nav && ! empty( $nav_item->primary ) ) { 1309 $span = strpos( $nav_item->name, '<span' ); 1310 1311 // Grab count out of the <span> element. 1312 if ( false !== $span ) { 1313 $count_start = strpos( $nav_item->name, '>', $span ) + 1; 1314 $count_end = strpos( $nav_item->name, '<', $count_start ); 1315 $count = (int) substr( $nav_item->name, $count_start, $count_end - $count_start ); 1316 } 1317 } 1318 1319 /** 1320 * Filter to edit the count attribute for the nav item. 1321 * 1322 * @since 3.0.0 1323 * 1324 * @param int $count The count attribute for the nav item. 1325 * @param object $nav_item The current nav item object. 1326 * @param string $value The current nav in use (eg: 'directory', 'groups', 'personal', etc..). 1327 */ 1328 return (int) apply_filters( 'bp_nouveau_get_nav_count', $count, $nav_item, $bp_nouveau->displayed_nav ); 1329 } 1330 1331 /** Template tags specific to the Directory navs ******************************/ 1332 1333 /** 1334 * Displays the directory nav class. 1335 * 1336 * @since 3.0.0 1337 */ 1338 function bp_nouveau_directory_type_navs_class() { 1339 echo esc_attr( bp_nouveau_get_directory_type_navs_class() ); 1340 } 1341 1342 /** 1343 * Provides default nav wrapper classes. 1344 * 1345 * Gets the directory component nav class. 1346 * Gets user selection Customizer options. 1347 * 1348 * @since 3.0.0 1349 * 1350 * @return string 1351 */ 1352 function bp_nouveau_get_directory_type_navs_class() { 1353 $component = sanitize_key( bp_current_component() ); 1354 1355 // If component is 'blogs' we need to access options as 'Sites'. 1356 if ('blogs' === $component) { 1357 $component = 'sites'; 1358 }; 1359 1360 $customizer_option = sprintf( '%s_dir_tabs', $component ); 1361 $nav_style = bp_nouveau_get_temporary_setting( $customizer_option, bp_nouveau_get_appearance_settings( $customizer_option ) ); 1362 $tab_style = ''; 1363 1364 if ( 1 === $nav_style ) { 1365 $tab_style = $component . '-nav-tabs'; 1366 } 1367 1368 $nav_wrapper_classes = array( 1369 sprintf( '%s-type-navs', $component ), 1370 'main-navs', 1371 'bp-navs', 1372 'dir-navs', 1373 $tab_style 1374 ); 1375 1376 /** 1377 * Filter to edit/add classes. 1378 * 1379 * NB: you can also directly add classes to the class attr. 1380 * 1381 * @since 3.0.0 1382 * 1383 * @param array $nav_wrapper_classes The list of classes. 1384 */ 1385 $nav_wrapper_classes = (array) apply_filters( 'bp_nouveau_get_directory_type_navs_class', $nav_wrapper_classes ); 1386 1387 return join( ' ', array_map( 'sanitize_html_class', $nav_wrapper_classes ) ); 1388 } 1389 1390 /** 1391 * Displays the directory nav item list class. 1392 * 1393 * @since 3.0.0 1394 */ 1395 function bp_nouveau_directory_list_class() { 1396 echo esc_attr( bp_nouveau_get_directory_list_class() ); 1397 } 1398 1399 /** 1400 * Gets the directory nav item list class. 1401 * 1402 * @since 3.0.0 1403 * 1404 * @return string 1405 */ 1406 function bp_nouveau_get_directory_list_class() { 1407 return sanitize_html_class( sprintf( '%s-nav', bp_current_component() ) ); 1408 } 1409 1410 /** 1411 * Displays the directory nav item object (data-bp attribute). 1412 * 1413 * @since 3.0.0 1414 */ 1415 function bp_nouveau_directory_nav_object() { 1416 $obj = bp_nouveau_get_directory_nav_object(); 1417 1418 if ( ! is_null( $obj ) ) { 1419 echo esc_attr( $obj ); 1420 } 1421 } 1422 1423 /** 1424 * Gets the directory nav item object. 1425 * 1426 * @see BP_Component::setup_nav(). 1427 * 1428 * @since 3.0.0 1429 * 1430 * @return array 1431 */ 1432 function bp_nouveau_get_directory_nav_object() { 1433 $nav_item = bp_nouveau()->current_nav_item; 1434 1435 if ( ! $nav_item->component ) { 1436 return null; 1437 } 1438 1439 return $nav_item->component; 1440 } 1441 1442 1443 // Template tags for the single item navs. 1444 1445 /** 1446 * Output main BuddyPress container classes. 1447 * 1448 * @since 3.0.0 1449 * 1450 * @return string CSS classes 1451 */ 1452 function bp_nouveau_container_classes() { 1453 echo esc_attr( bp_nouveau_get_container_classes() ); 1454 } 1455 1456 /** 1457 * Returns the main BuddyPress container classes. 1458 * 1459 * @since 3.0.0 1460 * @since 7.0.0 Add a class to inform about the active Theme. 1461 * 1462 * @return string CSS classes 1463 */ 1464 function bp_nouveau_get_container_classes() { 1465 $classes = array( 'buddypress-wrap', get_template() ); 1466 $component = bp_current_component(); 1467 $bp_nouveau = bp_nouveau(); 1468 $member_type_class = ''; 1469 1470 if ( bp_is_user() ) { 1471 $customizer_option = 'user_nav_display'; 1472 $component = 'members'; 1473 $user_type = bp_get_member_type( bp_displayed_user_id() ); 1474 $member_type_class = ( $user_type )? $user_type : ''; 1475 1476 } elseif ( bp_is_group() ) { 1477 $customizer_option = 'group_nav_display'; 1478 1479 } elseif ( bp_is_directory() ) { 1480 switch ( $component ) { 1481 case 'activity': 1482 $customizer_option = 'activity_dir_layout'; 1483 break; 1484 1485 case 'members': 1486 $customizer_option = 'members_dir_layout'; 1487 break; 1488 1489 case 'groups': 1490 $customizer_option = 'groups_dir_layout'; 1491 break; 1492 1493 case 'blogs': 1494 $customizer_option = 'sites_dir_layout'; 1495 break; 1496 1497 default: 1498 $customizer_option = ''; 1499 break; 1500 } 1501 1502 } else { 1503 /** 1504 * Filters the BuddyPress Nouveau single item setting ID. 1505 * 1506 * @since 3.0.0 1507 * 1508 * @param string $value Setting ID. 1509 */ 1510 $customizer_option = apply_filters( 'bp_nouveau_single_item_display_settings_id', '' ); 1511 } 1512 1513 if ( $member_type_class ) { 1514 $classes[] = $member_type_class; 1515 } 1516 1517 // Provide a class token to acknowledge additional extended profile fields added to default account reg screen 1518 if ( 'register' === bp_current_component() && bp_is_active( 'xprofile' ) && bp_nouveau_has_signup_xprofile_fields()) { 1519 $classes[] = 'extended-default-reg'; 1520 } 1521 1522 // Add classes according to site owners preferences. These are options set via Customizer. 1523 1524 // These are general site wide Cust options falling outside component checks 1525 $general_settings = bp_nouveau_get_temporary_setting( 'avatar_style', bp_nouveau_get_appearance_settings( 'avatar_style' ) ); 1526 if ( $general_settings ) { 1527 $classes[] = 'round-avatars'; 1528 } 1529 1530 // Set via earlier switch for component check to provide correct option key. 1531 if ( $customizer_option ) { 1532 $layout_prefs = bp_nouveau_get_temporary_setting( $customizer_option, bp_nouveau_get_appearance_settings( $customizer_option ) ); 1533 1534 if ( $layout_prefs && (int) $layout_prefs === 1 && ( bp_is_user() || bp_is_group() ) ) { 1535 $classes[] = 'bp-single-vert-nav'; 1536 $classes[] = 'bp-vertical-navs'; 1537 } 1538 1539 if ( $layout_prefs && bp_is_directory() ) { 1540 $classes[] = 'bp-dir-vert-nav'; 1541 $classes[] = 'bp-vertical-navs'; 1542 $bp_nouveau->{$component}->directory_vertical_layout = $layout_prefs; 1543 } else { 1544 $classes[] = 'bp-dir-hori-nav'; 1545 } 1546 } 1547 1548 $global_alignment = bp_nouveau_get_temporary_setting( 'global_alignment', bp_nouveau_get_appearance_settings( 'global_alignment' ) ); 1549 if ( $global_alignment && 'alignnone' !== $global_alignment && current_theme_supports( 'align-wide' ) ) { 1550 $classes[] = $global_alignment; 1551 } 1552 1553 $class = array_map( 'sanitize_html_class', $classes ); 1554 1555 /** 1556 * Filters the final results for BuddyPress Nouveau container classes. 1557 * 1558 * This filter will return a single string of concatenated classes to be used. 1559 * 1560 * @since 3.0.0 1561 * 1562 * @param string $value Concatenated classes. 1563 * @param array $classes Array of classes that were concatenated. 1564 */ 1565 return apply_filters( 'bp_nouveau_get_container_classes', join( ' ', $class ), $classes ); 1566 } 1567 1568 /** 1569 * Output single item nav container classes 1570 * 1571 * @since 3.0.0 1572 * 1573 * @return string CSS classes 1574 */ 1575 function bp_nouveau_single_item_nav_classes() { 1576 echo esc_attr( bp_nouveau_get_single_item_nav_classes() ); 1577 } 1578 1579 /** 1580 * Returns the single item nav container classes 1581 * 1582 * @since 3.0.0 1583 * 1584 * @return string CSS classes 1585 */ 1586 function bp_nouveau_get_single_item_nav_classes() { 1587 $classes = array( 'main-navs', 'no-ajax', 'bp-navs', 'single-screen-navs' ); 1588 $component = bp_current_component(); 1589 $bp_nouveau = bp_nouveau(); 1590 1591 // @todo wasn't able to get $customizer_option to pass a string to get_settings 1592 // this is a temp workaround but differs from earlier dir approach- bad! 1593 if ( bp_is_group() ) { 1594 $nav_tabs = (int) bp_nouveau_get_temporary_setting( 'group_nav_tabs', bp_nouveau_get_appearance_settings( 'group_nav_tabs' ) ); 1595 1596 } elseif ( bp_is_user() ) { 1597 $nav_tabs = (int) bp_nouveau_get_temporary_setting( 'user_nav_tabs', bp_nouveau_get_appearance_settings( 'user_nav_tabs' ) ); 1598 } 1599 1600 if ( bp_is_group() && 1 === $nav_tabs) { 1601 $classes[] = 'group-nav-tabs'; 1602 $classes[] = 'tabbed-links'; 1603 } elseif ( bp_is_user() && 1 === $nav_tabs ) { 1604 $classes[] = 'user-nav-tabs'; 1605 $classes[] = 'tabbed-links'; 1606 } 1607 1608 if ( bp_is_user() ) { 1609 $component = 'members'; 1610 $menu_type = 'users-nav'; 1611 } else { 1612 $menu_type = 'groups-nav'; 1613 } 1614 1615 $customizer_option = ( bp_is_user() )? 'user_nav_display' : 'group_nav_display'; 1616 1617 $layout_prefs = (int) bp_nouveau_get_temporary_setting( $customizer_option, bp_nouveau_get_appearance_settings( $customizer_option ) ); 1618 1619 // Set the global for a later use - this is moved from the `bp_nouveau_get_container_classes() 1620 // But was set as a check for this array class addition. 1621 $bp_nouveau->{$component}->single_primary_nav_layout = $layout_prefs; 1622 1623 if ( 1 === $layout_prefs ) { 1624 $classes[] = 'vertical'; 1625 } else { 1626 $classes[] = 'horizontal'; 1627 } 1628 1629 $classes[] = $menu_type; 1630 $class = array_map( 'sanitize_html_class', $classes ); 1631 1632 /** 1633 * Filters the final results for BuddyPress Nouveau single item nav classes. 1634 * 1635 * This filter will return a single string of concatenated classes to be used. 1636 * 1637 * @since 3.0.0 1638 * 1639 * @param string $value Concatenated classes. 1640 * @param array $classes Array of classes that were concatenated. 1641 */ 1642 return apply_filters( 'bp_nouveau_get_single_item_nav_classes', join( ' ', $class ), $classes ); 1643 } 1644 1645 /** 1646 * Output single item subnav container classes. 1647 * 1648 * @since 3.0.0 1649 * 1650 * @return string CSS classes 1651 */ 1652 function bp_nouveau_single_item_subnav_classes() { 1653 echo esc_attr( bp_nouveau_get_single_item_subnav_classes() ); 1654 } 1655 1656 /** 1657 * Returns the single item subnav container classes. 1658 * 1659 * @since 3.0.0 1660 * 1661 * @return string CSS classes 1662 */ 1663 function bp_nouveau_get_single_item_subnav_classes() { 1664 $classes = array( 'bp-navs', 'bp-subnavs', 'no-ajax' ); 1665 1666 // Set user or group class string 1667 if ( bp_is_user() ) { 1668 $classes[] = 'user-subnav'; 1669 } 1670 1671 if ( bp_is_group() ) { 1672 $classes[] = 'group-subnav'; 1673 } 1674 1675 if ( ( bp_is_group() && 'send-invites' === bp_current_action() ) || ( bp_is_group_create() && 'group-invites' === bp_get_groups_current_create_step() ) ) { 1676 $classes[] = 'bp-invites-nav'; 1677 } 1678 1679 $customizer_option = ( bp_is_user() )? 'user_subnav_tabs' : 'group_subnav_tabs'; 1680 $nav_tabs = (int) bp_nouveau_get_temporary_setting( $customizer_option, bp_nouveau_get_appearance_settings( $customizer_option ) ); 1681 1682 if ( bp_is_user() && 1 === $nav_tabs ) { 1683 $classes[] = 'tabbed-links'; 1684 } 1685 1686 if ( bp_is_group() && 1 === $nav_tabs ) { 1687 $classes[] = 'tabbed-links'; 1688 } 1689 1690 $class = array_map( 'sanitize_html_class', $classes ); 1691 1692 /** 1693 * Filters the final results for BuddyPress Nouveau single item subnav classes. 1694 * 1695 * This filter will return a single string of concatenated classes to be used. 1696 * 1697 * @since 3.0.0 1698 * 1699 * @param string $value Concatenated classes. 1700 * @param array $classes Array of classes that were concatenated. 1701 */ 1702 return apply_filters( 'bp_nouveau_get_single_item_subnav_classes', join( ' ', $class ), $classes ); 1703 } 1704 1705 /** 1706 * Output the groups create steps classes. 1707 * 1708 * @since 3.0.0 1709 * 1710 * @return string CSS classes 1711 */ 1712 function bp_nouveau_groups_create_steps_classes() { 1713 echo esc_attr( bp_nouveau_get_group_create_steps_classes() ); 1714 } 1715 1716 /** 1717 * Returns the groups create steps customizer option choice class. 1718 * 1719 * @since 3.0.0 1720 * 1721 * @return string CSS classes 1722 */ 1723 function bp_nouveau_get_group_create_steps_classes() { 1724 $classes = array( 'bp-navs', 'group-create-links', 'no-ajax' ); 1725 $nav_tabs = (int) bp_nouveau_get_temporary_setting( 'groups_create_tabs', bp_nouveau_get_appearance_settings( 'groups_create_tabs' ) ); 1726 1727 if ( 1 === $nav_tabs ) { 1728 $classes[] = 'tabbed-links'; 1729 } 1730 1731 $class = array_map( 'sanitize_html_class', $classes ); 1732 1733 /** 1734 * Filters the final results for BuddyPress Nouveau group creation step classes. 1735 * 1736 * This filter will return a single string of concatenated classes to be used. 1737 * 1738 * @since 3.0.0 1739 * 1740 * @param string $value Concatenated classes. 1741 * @param array $classes Array of classes that were concatenated. 1742 */ 1743 return apply_filters( 'bp_nouveau_get_group_create_steps_classes', join( ' ', $class ), $classes ); 1744 } 1745 1746 1747 /** Template tags for the object search **************************************/ 1748 1749 /** 1750 * Get the search primary object 1751 * 1752 * @since 3.0.0 1753 * 1754 * @param string $object Optional. The primary object. 1755 * 1756 * @return string The primary object. 1757 */ 1758 function bp_nouveau_get_search_primary_object( $object = '' ) { 1759 if ( bp_is_user() ) { 1760 $object = 'member'; 1761 } elseif ( bp_is_group() ) { 1762 $object = 'group'; 1763 } elseif ( bp_is_directory() ) { 1764 $object = 'dir'; 1765 } else { 1766 1767 /** 1768 * Filters the search primary object if no other was found. 1769 * 1770 * @since 3.0.0 1771 * 1772 * @param string $object Search object. 1773 */ 1774 $object = apply_filters( 'bp_nouveau_get_search_primary_object', $object ); 1775 } 1776 1777 return $object; 1778 } 1779 1780 /** 1781 * Get The list of search objects (primary + secondary). 1782 * 1783 * @since 3.0.0 1784 * 1785 * @param array $objects Optional. The list of objects. 1786 * 1787 * @return array The list of objects. 1788 */ 1789 function bp_nouveau_get_search_objects( $objects = array() ) { 1790 $primary = bp_nouveau_get_search_primary_object(); 1791 if ( ! $primary ) { 1792 return $objects; 1793 } 1794 1795 $objects = array( 1796 'primary' => $primary, 1797 ); 1798 1799 if ( 'member' === $primary || 'dir' === $primary ) { 1800 $objects['secondary'] = bp_current_component(); 1801 } elseif ( 'group' === $primary ) { 1802 $objects['secondary'] = bp_current_action(); 1803 1804 if ( bp_is_group_home() && ! bp_is_group_custom_front() ) { 1805 $objects['secondary'] = 'members'; 1806 1807 if ( bp_is_active( 'activity' ) ) { 1808 $objects['secondary'] = 'activity'; 1809 } 1810 } 1811 } else { 1812 1813 /** 1814 * Filters the search objects if no others were found. 1815 * 1816 * @since 3.0.0 1817 * 1818 * @param array $objects Search objects. 1819 */ 1820 $objects = apply_filters( 'bp_nouveau_get_search_objects', $objects ); 1821 } 1822 1823 return $objects; 1824 } 1825 1826 /** 1827 * Output the search form container classes. 1828 * 1829 * @since 3.0.0 1830 */ 1831 function bp_nouveau_search_container_class() { 1832 $objects = bp_nouveau_get_search_objects(); 1833 $class = join( '-search ', array_map( 'sanitize_html_class', $objects ) ) . '-search'; 1834 1835 echo esc_attr( $class ); 1836 } 1837 1838 /** 1839 * Output the search form data-bp attribute. 1840 * 1841 * @since 3.0.0 1842 * 1843 * @param string $attr The data-bp attribute. 1844 * @return string The data-bp attribute. 1845 */ 1846 function bp_nouveau_search_object_data_attr( $attr = '' ) { 1847 $objects = bp_nouveau_get_search_objects(); 1848 1849 if ( ! isset( $objects['secondary'] ) ) { 1850 return $attr; 1851 } 1852 1853 if ( bp_is_active( 'groups' ) && bp_is_group_members() ) { 1854 $attr = join( '_', $objects ); 1855 } else { 1856 $attr = $objects['secondary']; 1857 } 1858 1859 echo esc_attr( $attr ); 1860 } 1861 1862 /** 1863 * Output a selector ID. 1864 * 1865 * @since 3.0.0 1866 * 1867 * @param string $suffix Optional. A string to append at the end of the ID. 1868 * @param string $sep Optional. The separator to use between each token. 1869 * 1870 * @return string The selector ID. 1871 */ 1872 function bp_nouveau_search_selector_id( $suffix = '', $sep = '-' ) { 1873 $id = join( $sep, array_merge( bp_nouveau_get_search_objects(), (array) $suffix ) ); 1874 echo esc_attr( $id ); 1875 } 1876 1877 /** 1878 * Output the name attribute of a selector. 1879 * 1880 * @since 3.0.0 1881 * 1882 * @param string $suffix Optional. A string to append at the end of the name. 1883 * @param string $sep Optional. The separator to use between each token. 1884 * 1885 * @return string The name attribute of a selector. 1886 */ 1887 function bp_nouveau_search_selector_name( $suffix = '', $sep = '_' ) { 1888 $objects = bp_nouveau_get_search_objects(); 1889 1890 if ( isset( $objects['secondary'] ) && ! $suffix ) { 1891 $name = bp_core_get_component_search_query_arg( $objects['secondary'] ); 1892 } else { 1893 $name = join( $sep, array_merge( $objects, (array) $suffix ) ); 1894 } 1895 1896 echo esc_attr( $name ); 1897 } 1898 1899 /** 1900 * Output the default search text for the search object 1901 * 1902 * @since 3.0.0 1903 * 1904 * @param string $text Optional. The default search text for the search object. 1905 * @param string $is_attr Optional. True if it's to be output inside an attribute. False Otherwise. 1906 * 1907 * @return string The default search text. 1908 * 1909 * @todo 28/09/17 added 'empty( $text )' check to $object query as it wasn't returning output as expected & not returning user set params 1910 * This may require further examination - hnla 1911 */ 1912 function bp_nouveau_search_default_text( $text = '', $is_attr = true ) { 1913 $objects = bp_nouveau_get_search_objects(); 1914 1915 if ( ! empty( $objects['secondary'] ) && empty( $text ) ) { 1916 $text = bp_get_search_default_text( $objects['secondary'] ); 1917 } 1918 1919 if ( $is_attr ) { 1920 echo esc_attr( $text ); 1921 } else { 1922 echo esc_html( $text ); 1923 } 1924 } 1925 1926 /** 1927 * Get the search form template part and fire some do_actions if needed. 1928 * 1929 * @since 3.0.0 1930 */ 1931 function bp_nouveau_search_form() { 1932 $search_form_html = bp_buffer_template_part( 'common/search/search-form', null, false ); 1933 1934 $objects = bp_nouveau_get_search_objects(); 1935 if ( empty( $objects['primary'] ) || empty( $objects['secondary'] ) ) { 1936 echo $search_form_html; 1937 return; 1938 } 1939 1940 if ( 'dir' === $objects['primary'] ) { 1941 /** 1942 * Filter here to edit the HTML output of the directory search form. 1943 * 1944 * NB: This will take in charge the following BP Core Components filters 1945 * - bp_directory_members_search_form 1946 * - bp_directory_blogs_search_form 1947 * - bp_directory_groups_search_form 1948 * 1949 * @since 1.9.0 1950 * 1951 * @param string $search_form_html The HTML output for the directory search form. 1952 */ 1953 echo apply_filters( "bp_directory_{$objects['secondary']}_search_form", $search_form_html ); 1954 1955 if ( 'activity' === $objects['secondary'] ) { 1956 /** 1957 * Fires before the display of the activity syndication options. 1958 * 1959 * @since 1.2.0 1960 */ 1961 do_action( 'bp_activity_syndication_options' ); 1962 1963 } elseif ( 'blogs' === $objects['secondary'] ) { 1964 /** 1965 * Fires inside the unordered list displaying blog sub-types. 1966 * 1967 * @since 1.5.0 1968 */ 1969 do_action( 'bp_blogs_directory_blog_sub_types' ); 1970 1971 } elseif ( 'groups' === $objects['secondary'] ) { 1972 /** 1973 * Fires inside the groups directory group types. 1974 * 1975 * @since 1.2.0 1976 */ 1977 do_action( 'bp_groups_directory_group_types' ); 1978 1979 } elseif ( 'members' === $objects['secondary'] ) { 1980 /** 1981 * Fires inside the members directory member sub-types. 1982 * 1983 * @since 1.5.0 1984 */ 1985 do_action( 'bp_members_directory_member_sub_types' ); 1986 } 1987 } elseif ( 'group' === $objects['primary'] ) { 1988 if ( 'members' !== $objects['secondary'] ) { 1989 /** 1990 * Filter here to edit the HTML output of the displayed group search form. 1991 * 1992 * @since 3.2.0 1993 * 1994 * @param string $search_form_html The HTML output for the directory search form. 1995 */ 1996 echo apply_filters( "bp_group_{$objects['secondary']}_search_form", $search_form_html ); 1997 1998 } else { 1999 /** 2000 * Filters the Members component search form. 2001 * 2002 * @since 1.9.0 2003 * 2004 * @param string $search_form_html HTML markup for the member search form. 2005 */ 2006 echo apply_filters( 'bp_directory_members_search_form', $search_form_html ); 2007 } 2008 2009 if ( 'members' === $objects['secondary'] ) { 2010 /** 2011 * Fires at the end of the group members search unordered list. 2012 * 2013 * Part of bp_groups_members_template_part(). 2014 * 2015 * @since 1.5.0 2016 */ 2017 do_action( 'bp_members_directory_member_sub_types' ); 2018 2019 } elseif ( 'activity' === $objects['secondary'] ) { 2020 /** 2021 * Fires inside the syndication options list, after the RSS option. 2022 * 2023 * @since 1.2.0 2024 */ 2025 do_action( 'bp_group_activity_syndication_options' ); 2026 } 2027 } 2028 } 2029 2030 2031 // Template tags for the directory & user/group screen filters. 2032 2033 /** 2034 * Get the current component or action. 2035 * 2036 * If on single group screens we need to switch from component to bp_current_action() to add the correct 2037 * IDs/labels for group/activity & similar screens. 2038 * 2039 * @since 3.0.0 2040 */ 2041 function bp_nouveau_current_object() { 2042 /* 2043 * If we're looking at groups single screens we need to factor in current action 2044 * to avoid the component check adding the wrong id for the main dir e.g 'groups' instead of 'activity'. 2045 * We also need to check for group screens to adjust the id's for prefixes. 2046 */ 2047 $component = array(); 2048 2049 if ( bp_is_group() ) { 2050 $component['members_select'] = 'groups_members-order-select'; 2051 $component['members_order_by'] = 'groups_members-order-by'; 2052 $component['object'] = bp_current_action(); 2053 $component['data_filter'] = bp_current_action(); 2054 2055 if ( 'activity' !== bp_current_action() ) { 2056 /** 2057 * If the Group's front page is not used, Activities are displayed on Group's home page. 2058 * To make sure filters are behaving the right way, we need to override the component object 2059 * and data filter to `activity`. 2060 */ 2061 if ( bp_is_group_activity() ) { 2062 $activity_id = buddypress()->activity->id; 2063 $component['object'] = $activity_id; 2064 $component['data_filter'] = $activity_id; 2065 } else { 2066 $component['data_filter'] = 'group_' . bp_current_action(); 2067 } 2068 } 2069 2070 } else { 2071 $component_id = bp_current_component(); 2072 if ( ! bp_is_directory() ) { 2073 $component_id = bp_core_get_active_components( array( 'slug' => $component_id ) ); 2074 $component_id = reset( $component_id ); 2075 } 2076 2077 $data_filter = $component_id; 2078 2079 if ( 'friends' === $data_filter && bp_is_user_friend_requests() ) { 2080 $data_filter = 'friend_requests'; 2081 } 2082 2083 $component['members_select'] = 'members-order-select'; 2084 $component['members_order_by'] = 'members-order-by'; 2085 $component['object'] = $component_id; 2086 $component['data_filter'] = $data_filter; 2087 } 2088 2089 return $component; 2090 } 2091 2092 /** 2093 * Output data filter container's ID attribute value. 2094 * 2095 * @since 3.0.0 2096 */ 2097 function bp_nouveau_filter_container_id() { 2098 echo esc_attr( bp_nouveau_get_filter_container_id() ); 2099 } 2100 2101 /** 2102 * Get data filter container's ID attribute value. 2103 * 2104 * @since 3.0.0 2105 * 2106 * @param string 2107 */ 2108 function bp_nouveau_get_filter_container_id() { 2109 $component = bp_nouveau_current_object(); 2110 2111 $ids = array( 2112 'members' => $component['members_select'], 2113 'friends' => 'members-friends-select', 2114 'notifications' => 'notifications-filter-select', 2115 'activity' => 'activity-filter-select', 2116 'groups' => 'groups-order-select', 2117 'blogs' => 'blogs-order-select', 2118 ); 2119 2120 if ( isset( $ids[ $component['object'] ] ) ) { 2121 2122 /** 2123 * Filters the container ID for BuddyPress Nouveau filters. 2124 * 2125 * @since 3.0.0 2126 * 2127 * @param string $value ID based on current component object. 2128 */ 2129 return apply_filters( 'bp_nouveau_get_filter_container_id', $ids[ $component['object'] ] ); 2130 } 2131 2132 return ''; 2133 } 2134 2135 /** 2136 * Output data filter's ID attribute value. 2137 * 2138 * @since 3.0.0 2139 */ 2140 function bp_nouveau_filter_id() { 2141 echo esc_attr( bp_nouveau_get_filter_id() ); 2142 } 2143 2144 /** 2145 * Get data filter's ID attribute value. 2146 * 2147 * @since 3.0.0 2148 * 2149 * @param string 2150 */ 2151 function bp_nouveau_get_filter_id() { 2152 $component = bp_nouveau_current_object(); 2153 2154 $ids = array( 2155 'members' => $component['members_order_by'], 2156 'friends' => 'members-friends', 2157 'notifications' => 'notifications-filter-by', 2158 'activity' => 'activity-filter-by', 2159 'groups' => 'groups-order-by', 2160 'blogs' => 'blogs-order-by', 2161 ); 2162 2163 if ( isset( $ids[ $component['object'] ] ) ) { 2164 2165 /** 2166 * Filters the filter ID for BuddyPress Nouveau filters. 2167 * 2168 * @since 3.0.0 2169 * 2170 * @param string $value ID based on current component object. 2171 */ 2172 return apply_filters( 'bp_nouveau_get_filter_id', $ids[ $component['object'] ] ); 2173 } 2174 2175 return ''; 2176 } 2177 2178 /** 2179 * Output data filter's label. 2180 * 2181 * @since 3.0.0 2182 */ 2183 function bp_nouveau_filter_label() { 2184 echo esc_html( bp_nouveau_get_filter_label() ); 2185 } 2186 2187 /** 2188 * Get data filter's label. 2189 * 2190 * @since 3.0.0 2191 * 2192 * @param string 2193 */ 2194 function bp_nouveau_get_filter_label() { 2195 $component = bp_nouveau_current_object(); 2196 $label = __( 'Order By:', 'buddypress' ); 2197 2198 if ( 'activity' === $component['object'] || 'friends' === $component['object'] ) { 2199 $label = __( 'Show:', 'buddypress' ); 2200 } 2201 2202 /** 2203 * Filters the label for BuddyPress Nouveau filters. 2204 * 2205 * @since 3.0.0 2206 * 2207 * @param string $label Label for BuddyPress Nouveau filter. 2208 * @param array $component The data filter's data-bp-filter attribute value. 2209 */ 2210 return apply_filters( 'bp_nouveau_get_filter_label', $label, $component ); 2211 } 2212 2213 /** 2214 * Output data filter's data-bp-filter attribute value. 2215 * 2216 * @since 3.0.0 2217 */ 2218 function bp_nouveau_filter_component() { 2219 $component = bp_nouveau_current_object(); 2220 echo esc_attr( $component['data_filter'] ); 2221 } 2222 2223 /** 2224 * Output the <option> of the data filter's <select> element. 2225 * 2226 * @since 3.0.0 2227 */ 2228 function bp_nouveau_filter_options() { 2229 echo bp_nouveau_get_filter_options(); // Escaped in inner functions. 2230 } 2231 2232 /** 2233 * Get the <option> of the data filter's <select> element. 2234 * 2235 * @since 3.0.0 2236 * 2237 * @return string 2238 */ 2239 function bp_nouveau_get_filter_options() { 2240 $output = ''; 2241 2242 if ( bp_get_notifications_slug() === bp_current_component() ) { 2243 $output = bp_nouveau_get_notifications_filters(); 2244 2245 } else { 2246 $filters = bp_nouveau_get_component_filters(); 2247 2248 foreach ( $filters as $key => $value ) { 2249 $output .= sprintf( '<option value="%1$s">%2$s</option>%3$s', 2250 esc_attr( $key ), 2251 esc_html( $value ), 2252 PHP_EOL 2253 ); 2254 } 2255 } 2256 2257 return $output; 2258 } 2259 2260 2261 /** Template tags for the Customizer ******************************************/ 2262 2263 /** 2264 * Get a link to reach a specific section into the customizer 2265 * 2266 * @since 3.0.0 2267 * 2268 * @param array $args Optional. The argument to customize the Customizer link. 2269 * 2270 * @return string HTML. 2271 */ 2272 function bp_nouveau_get_customizer_link( $args = array() ) { 2273 $r = bp_parse_args( $args, array( 2274 'capability' => 'bp_moderate', 2275 'object' => 'user', 2276 'item_id' => 0, 2277 'autofocus' => '', 2278 'text' => '', 2279 ), 'nouveau_get_customizer_link' ); 2280 2281 if ( empty( $r['capability'] ) || empty( $r['autofocus'] ) || empty( $r['text'] ) ) { 2282 return ''; 2283 } 2284 2285 if ( ! bp_current_user_can( $r['capability'] ) ) { 2286 return ''; 2287 } 2288 2289 $url = ''; 2290 2291 if ( bp_is_user() ) { 2292 $url = rawurlencode( bp_displayed_user_domain() ); 2293 2294 } elseif ( bp_is_group() ) { 2295 $url = rawurlencode( bp_get_group_permalink( groups_get_current_group() ) ); 2296 2297 } elseif ( ! empty( $r['object'] ) && ! empty( $r['item_id'] ) ) { 2298 if ( 'user' === $r['object'] ) { 2299 $url = rawurlencode( bp_core_get_user_domain( $r['item_id'] ) ); 2300 2301 } elseif ( 'group' === $r['object'] ) { 2302 $group = groups_get_group( array( 'group_id' => $r['item_id'] ) ); 2303 2304 if ( ! empty( $group->id ) ) { 2305 $url = rawurlencode( bp_get_group_permalink( $group ) ); 2306 } 2307 } 2308 } 2309 2310 if ( ! $url ) { 2311 return ''; 2312 } 2313 2314 $customizer_link = add_query_arg( array( 2315 'autofocus[section]' => $r['autofocus'], 2316 'url' => $url, 2317 ), admin_url( 'customize.php' ) ); 2318 2319 return sprintf( '<a href="%1$s">%2$s</a>', esc_url( $customizer_link ), esc_html( $r['text'] ) ); 2320 } 2321 2322 /** Template tags for signup forms *******************************************/ 2323 2324 /** 2325 * Fire specific hooks into the register template 2326 * 2327 * @since 3.0.0 2328 * 2329 * @param string $when 'before' or 'after' 2330 * @param string $prefix Use it to add terms before the hook name 2331 */ 2332 function bp_nouveau_signup_hook( $when = '', $prefix = '' ) { 2333 $hook = array( 'bp' ); 2334 2335 if ( $when ) { 2336 $hook[] = $when; 2337 } 2338 2339 if ( $prefix ) { 2340 if ( 'page' === $prefix ) { 2341 $hook[] = 'register'; 2342 } elseif ( 'steps' === $prefix ) { 2343 $hook[] = 'signup'; 2344 } 2345 2346 $hook[] = $prefix; 2347 } 2348 2349 if ( 'page' !== $prefix && 'steps' !== $prefix ) { 2350 $hook[] = 'fields'; 2351 } 2352 2353 bp_nouveau_hook( $hook ); 2354 } 2355 2356 /** 2357 * Fire specific hooks into the activate template 2358 * 2359 * @since 3.0.0 2360 * 2361 * @param string $when 'before' or 'after' 2362 * @param string $prefix Use it to add terms before the hook name 2363 */ 2364 function bp_nouveau_activation_hook( $when = '', $suffix = '' ) { 2365 $hook = array( 'bp' ); 2366 2367 if ( $when ) { 2368 $hook[] = $when; 2369 } 2370 2371 $hook[] = 'activate'; 2372 2373 if ( $suffix ) { 2374 $hook[] = $suffix; 2375 } 2376 2377 if ( 'page' === $suffix ) { 2378 $hook[2] = 'activation'; 2379 } 2380 2381 bp_nouveau_hook( $hook ); 2382 } 2383 2384 /** 2385 * Output the signup form for the requested section 2386 * 2387 * @since 3.0.0 2388 * 2389 * @param string $section Optional. The section of fields to get 'account_details' or 'blog_details'. 2390 * Default: 'account_details'. 2391 */ 2392 function bp_nouveau_signup_form( $section = 'account_details' ) { 2393 $fields = bp_nouveau_get_signup_fields( $section ); 2394 if ( ! $fields ) { 2395 return; 2396 } 2397 2398 foreach ( $fields as $name => $attributes ) { 2399 if ( 'signup_password' === $name ) { 2400 ?> 2401 <label for="pass1"><?php esc_html_e( 'Choose a Password (required)', 'buddypress' ); ?></label> 2402 <div class="user-pass1-wrap"> 2403 <div class="wp-pwd"> 2404 <div class="password-input-wrapper"> 2405 <input type="password" data-reveal="1" name="signup_password" id="pass1" class="password-entry" size="24" value="" <?php bp_form_field_attributes( 'password', array( 'data-pw' => wp_generate_password( 12 ), 'aria-describedby' => 'pass-strength-result' ) ); ?> /> 2406 <button type="button" class="button wp-hide-pw"> 2407 <span class="dashicons dashicons-hidden" aria-hidden="true"></span> 2408 </button> 2409 </div> 2410 <div id="pass-strength-result" aria-live="polite"><?php esc_html_e( 'Strength indicator', 'buddypress' ); ?></div> 2411 </div> 2412 <div class="pw-weak"> 2413 <label> 2414 <input type="checkbox" name="pw_weak" class="pw-checkbox" /> 2415 <?php esc_html_e( 'Confirm use of weak password', 'buddypress' ); ?> 2416 </label> 2417 </div> 2418 </div> 2419 <?php 2420 } elseif ( 'signup_password_confirm' === $name ) { 2421 ?> 2422 <p class="user-pass2-wrap"> 2423 <label for="pass2"><?php esc_html_e( 'Confirm new password', 'buddypress' ); ?></label><br /> 2424 <input type="password" name="signup_password_confirm" id="pass2" class="password-entry-confirm" size="24" value="" <?php bp_form_field_attributes( 'password' ); ?> /> 2425 </p> 2426 2427 <p class="description indicator-hint"><?php echo wp_get_password_hint(); ?></p> 2428 <?php 2429 } else { 2430 list( $label, $required, $value, $attribute_type, $type, $class ) = array_values( $attributes ); 2431 2432 // Text fields are using strings, radios are using their inputs 2433 $label_output = '<label for="%1$s">%2$s</label>'; 2434 $id = $name; 2435 $classes = ''; 2436 2437 if ( $required ) { 2438 /* translators: Do not translate placeholders. 2 = form field name, 3 = "(required)". */ 2439 $label_output = __( '<label for="%1$s">%2$s %3$s</label>', 'buddypress' ); 2440 } 2441 2442 // Output the label for regular fields 2443 if ( 'radio' !== $type ) { 2444 if ( $required ) { 2445 printf( $label_output, esc_attr( $name ), esc_html( $label ), __( '(required)', 'buddypress' ) ); 2446 } else { 2447 printf( $label_output, esc_attr( $name ), esc_html( $label ) ); 2448 } 2449 2450 if ( ! empty( $value ) && is_callable( $value ) ) { 2451 $value = call_user_func( $value ); 2452 } 2453 2454 // Handle the specific case of Site's privacy differently 2455 } elseif ( 'signup_blog_privacy_private' !== $name ) { 2456 ?> 2457 <span class="label"> 2458 <?php esc_html_e( 'I would like my site to appear in search engines, and in public listings around this network.', 'buddypress' ); ?> 2459 </span> 2460 <?php 2461 } 2462 2463 // Set the additional attributes 2464 if ( $attribute_type ) { 2465 $existing_attributes = array(); 2466 2467 if ( ! empty( $required ) ) { 2468 $existing_attributes = array( 'aria-required' => 'true' ); 2469 2470 /** 2471 * The blog section is hidden, so let's avoid a browser warning 2472 * and deal with the Blog section in Javascript. 2473 */ 2474 if ( $section !== 'blog_details' ) { 2475 $existing_attributes['required'] = 'required'; 2476 } 2477 } 2478 2479 $attribute_type = ' ' . bp_get_form_field_attributes( $attribute_type, $existing_attributes ); 2480 } 2481 2482 // Specific case for Site's privacy 2483 if ( 'signup_blog_privacy_public' === $name || 'signup_blog_privacy_private' === $name ) { 2484 $name = 'signup_blog_privacy'; 2485 $submitted = bp_get_signup_blog_privacy_value(); 2486 2487 if ( ! $submitted ) { 2488 $submitted = 'public'; 2489 } 2490 2491 $attribute_type = ' ' . checked( $value, $submitted, false ); 2492 } 2493 2494 // Do not run function to display errors for the private radio. 2495 if ( 'private' !== $value ) { 2496 2497 /** 2498 * Fetch & display any BP member registration field errors. 2499 * 2500 * Passes BP signup errors to Nouveau's template function to 2501 * render suitable markup for error string. 2502 */ 2503 if ( isset( buddypress()->signup->errors[ $name ] ) ) { 2504 nouveau_error_template( buddypress()->signup->errors[ $name ] ); 2505 $invalid = 'invalid'; 2506 } 2507 } 2508 2509 if ( isset( $invalid ) && isset( buddypress()->signup->errors[ $name ] ) ) { 2510 if ( ! empty( $class ) ) { 2511 $class = $class . ' ' . $invalid; 2512 } else { 2513 $class = $invalid; 2514 } 2515 } 2516 2517 if ( $class ) { 2518 $class = sprintf( 2519 ' class="%s"', 2520 esc_attr( join( ' ', array_map( 'sanitize_html_class', explode( ' ', $class ) ) ) ) 2521 ); 2522 } 2523 2524 // Set the input. 2525 $field_output = sprintf( 2526 '<input type="%1$s" name="%2$s" id="%3$s" %4$s value="%5$s" %6$s />', 2527 esc_attr( $type ), 2528 esc_attr( $name ), 2529 esc_attr( $id ), 2530 $class, // Constructed safely above. 2531 esc_attr( $value ), 2532 $attribute_type // Constructed safely above. 2533 ); 2534 2535 // Not a radio, let's output the field 2536 if ( 'radio' !== $type ) { 2537 if ( 'signup_blog_url' !== $name ) { 2538 print( $field_output ); // Constructed safely above. 2539 2540 // If it's the signup blog url, it's specific to Multisite config. 2541 } elseif ( is_subdomain_install() ) { 2542 // Constructed safely above. 2543 printf( 2544 '%1$s %2$s . %3$s', 2545 is_ssl() ? 'https://' : 'http://', 2546 $field_output, 2547 bp_signup_get_subdomain_base() 2548 ); 2549 2550 // Subfolders! 2551 } else { 2552 printf( 2553 '%1$s %2$s', 2554 home_url( '/' ), 2555 $field_output // Constructed safely above. 2556 ); 2557 } 2558 2559 // It's a radio, let's output the field inside the label 2560 } else { 2561 // $label_output and $field_output are constructed safely above. 2562 printf( $label_output, esc_attr( $name ), $field_output . ' ' . esc_html( $label ) ); 2563 } 2564 } 2565 } 2566 2567 /** 2568 * Fires and displays any extra member registration details fields. 2569 * 2570 * This is a variable hook that depends on the current section. 2571 * 2572 * @since 1.9.0 2573 */ 2574 do_action( "bp_{$section}_fields" ); 2575 } 2576 2577 /** 2578 * Outputs the Privacy Policy acceptance area on the registration page. 2579 * 2580 * @since 4.0.0 2581 */ 2582 function bp_nouveau_signup_privacy_policy_acceptance_section() { 2583 $error = null; 2584 if ( isset( buddypress()->signup->errors['signup_privacy_policy'] ) ) { 2585 $error = buddypress()->signup->errors['signup_privacy_policy']; 2586 } 2587 2588 ?> 2589 2590 <div class="privacy-policy-accept"> 2591 <?php if ( $error ) : ?> 2592 <?php nouveau_error_template( $error ); ?> 2593 <?php endif; ?> 2594 2595 <label for="signup-privacy-policy-accept"> 2596 <input type="hidden" name="signup-privacy-policy-check" value="1" /> 2597 2598 <?php /* translators: link to Privacy Policy */ ?> 2599 <input type="checkbox" name="signup-privacy-policy-accept" id="signup-privacy-policy-accept" required /> <?php printf( esc_html__( 'I have read and agree to this site\'s %s.', 'buddypress' ), sprintf( '<a href="%s">%s</a>', esc_url( get_privacy_policy_url() ), esc_html__( 'Privacy Policy', 'buddypress' ) ) ); ?> 2600 </label> 2601 </div> 2602 2603 <?php 2604 } 2605 2606 /** 2607 * Output a submit button and the nonce for the requested action. 2608 * 2609 * @since 3.0.0 2610 * 2611 * @param string $action The action to get the submit button for. Required. 2612 */ 2613 function bp_nouveau_submit_button( $action, $object_id = 0 ) { 2614 $submit_data = bp_nouveau_get_submit_button( $action ); 2615 if ( empty( $submit_data['attributes'] ) || empty( $submit_data['nonce'] ) ) { 2616 return; 2617 } 2618 2619 if ( ! empty( $submit_data['before'] ) ) { 2620 2621 /** 2622 * Fires before display of the submit button. 2623 * 2624 * This is a dynamic filter that is dependent on the "before" value provided by bp_nouveau_get_submit_button(). 2625 * 2626 * @since 3.0.0 2627 */ 2628 do_action( $submit_data['before'] ); 2629 } 2630 2631 $submit_input = sprintf( '<input type="submit" %s/>', 2632 bp_get_form_field_attributes( 'submit', $submit_data['attributes'] ) // Safe. 2633 ); 2634 2635 // Output the submit button. 2636 if ( isset( $submit_data['wrapper'] ) && false === $submit_data['wrapper'] ) { 2637 echo $submit_input; 2638 2639 // Output the submit button into a wrapper. 2640 } else { 2641 printf( '<div class="submit">%s</div>', $submit_input ); 2642 } 2643 2644 if ( empty( $submit_data['nonce_key'] ) ) { 2645 wp_nonce_field( $submit_data['nonce'] ); 2646 } else { 2647 if ( $object_id ) { 2648 $submit_data['nonce_key'] .= '_' . (int) $object_id; 2649 } 2650 2651 wp_nonce_field( $submit_data['nonce'], $submit_data['nonce_key'] ); 2652 } 2653 2654 if ( ! empty( $submit_data['after'] ) ) { 2655 2656 /** 2657 * Fires before display of the submit button. 2658 * 2659 * This is a dynamic filter that is dependent on the "after" value provided by bp_nouveau_get_submit_button(). 2660 * 2661 * @since 3.0.0 2662 */ 2663 do_action( $submit_data['after'] ); 2664 } 2665 } 2666 2667 /** 2668 * Display supplemental error or feedback messages. 2669 * 2670 * This template handles in page error or feedback messages e.g signup fields 2671 * 'Username exists' type registration field error notices. 2672 * 2673 * @param string $message required: the message to display. 2674 * @param string $type optional: the type of error message e.g 'error'. 2675 * 2676 * @since 3.0.0 2677 */ 2678 function nouveau_error_template( $message = '', $type = '' ) { 2679 if ( ! $message ) { 2680 return; 2681 } 2682 2683 $type = ( $type ) ? $type : 'error'; 2684 ?> 2685 2686 <div class="<?php echo esc_attr( 'bp-messages bp-feedback ' . $type ); ?>"> 2687 <span class="bp-icon" aria-hidden="true"></span> 2688 <p><?php echo esc_html( $message ); ?></p> 2689 </div> 2690 2691 <?php 2692 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Apr 21 01:01:43 2021 | Cross-referenced by PHPXref 0.7.1 |