[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-templates/bp-nouveau/includes/ -> template-tags.php (source)

   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  }


Generated: Wed Apr 21 01:01:43 2021 Cross-referenced by PHPXref 0.7.1