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


Generated: Tue Mar 19 01:01:09 2024 Cross-referenced by PHPXref 0.7.1