[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-templates/bp-nouveau/includes/groups/ -> functions.php (source)

   1  <?php
   2  /**
   3   * Groups functions
   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   * Provide a convenience function to add markup wrapper for message strings
  14   *
  15   * @param string $message The message text string
  16   * @param string $type    The message type - 'error, 'info', 'warning', success'
  17   *
  18   * @return string
  19   *
  20   * @since 3.0
  21   */
  22  function bp_nouveau_message_markup_wrapper( $message, $type ) {
  23      if ( ! $message ) {
  24          return false;
  25      }
  26  
  27      $message = '<div class=" ' . esc_attr( "bp-feedback {$type}" ) . '"><span class="bp-icon" aria-hidden="true"></span><p>' . esc_html( $message ) . '</p></div>';
  28  
  29      return $message;
  30  }
  31  
  32  /**
  33   * Register Scripts for the Groups component
  34   *
  35   * @since 3.0.0
  36   *
  37   * @param array $scripts Optional. The array of scripts to register.
  38   *
  39   * @return array The same array with the specific groups scripts.
  40   */
  41  function bp_nouveau_groups_register_scripts( $scripts = array() ) {
  42      if ( ! isset( $scripts['bp-nouveau'] ) ) {
  43          return $scripts;
  44      }
  45  
  46      return array_merge( $scripts, array(
  47          'bp-nouveau-group-invites' => array(
  48              'file'         => 'js/buddypress-group-invites%s.js',
  49              'dependencies' => array( 'bp-nouveau', 'json2', 'wp-backbone' ),
  50              'footer'       => true,
  51          ),
  52      ) );
  53  }
  54  
  55  /**
  56   * Enqueue the groups scripts
  57   *
  58   * @since 3.0.0
  59   */
  60  function bp_nouveau_groups_enqueue_scripts() {
  61      // Neutralize Ajax when using BuddyPress Groups & member widgets on default front page
  62      if ( bp_is_group_home() && bp_nouveau_get_appearance_settings( 'group_front_page' ) ) {
  63          wp_add_inline_style( 'bp-nouveau', '
  64              #group-front-widgets #groups-list-options,
  65              #group-front-widgets #members-list-options {
  66                  display: none;
  67              }
  68          ' );
  69      }
  70  
  71      if ( bp_is_group_invites() || ( bp_is_group_create() && bp_is_group_creation_step( 'group-invites' ) ) ) {
  72          wp_enqueue_script( 'bp-nouveau-group-invites' );
  73      }
  74  
  75      if ( bp_rest_api_is_available() && bp_is_group_admin_page() && bp_is_group_admin_screen( 'manage-members' ) ) {
  76          wp_enqueue_script( 'bp-group-manage-members' );
  77          wp_localize_script(
  78              'bp-group-manage-members',
  79              'bpGroupManageMembersSettings',
  80              bp_groups_get_group_manage_members_script_data( bp_get_current_group_id() )
  81          );
  82      }
  83  }
  84  
  85  /**
  86   * Can all members be invited to join any group?
  87   *
  88   * @since 3.0.0
  89   *
  90   * @param bool $default False to allow. True to disallow.
  91   *
  92   * @return bool
  93   */
  94  function bp_nouveau_groups_disallow_all_members_invites( $default = false ) {
  95      /**
  96       * Filter to remove the All members nav, returning true
  97       *
  98       * @since 3.0.0
  99       *
 100       * @param bool $default True to disable the nav. False otherwise.
 101       */
 102      return apply_filters( 'bp_nouveau_groups_disallow_all_members_invites', $default );
 103  }
 104  
 105  /**
 106   * Activate the Groups invitations feature if any member can be invited.
 107   *
 108   * @since 10.0.0
 109   *
 110   * @param bool True if any member can be invited. False otherwise.
 111   */
 112  function bp_nouveau_is_groups_invitations_active() {
 113      return ! bp_nouveau_groups_disallow_all_members_invites();
 114  }
 115  add_filter( 'bp_is_groups_invitations_active', 'bp_nouveau_is_groups_invitations_active' );
 116  
 117  /**
 118   * Localize the strings needed for the Group's Invite UI
 119   *
 120   * @since 3.0.0
 121   *
 122   * @param array $params Associative array containing the JS Strings needed by scripts
 123   *
 124   * @return array The same array with specific strings for the Group's Invite UI if needed.
 125   */
 126  function bp_nouveau_groups_localize_scripts( $params = array() ) {
 127      if ( ! bp_is_group_invites() && ! ( bp_is_group_create() && bp_is_group_creation_step( 'group-invites' ) ) ) {
 128          return $params;
 129      }
 130  
 131      $show_pending = bp_group_has_invites( array( 'user_id' => 'any' ) ) && ! bp_is_group_create();
 132  
 133      // Init the Group invites nav
 134      $invites_nav = array(
 135          'members' => array(
 136              'id'      => 'members',
 137              'caption' => __( 'All Members', 'buddypress' ),
 138              'order'   => 5,
 139          ),
 140          'invited' => array(
 141              'id'      => 'invited',
 142              'caption' => __( 'Pending Invites', 'buddypress' ),
 143              'order'   => 90,
 144              'hide'    => (int) ! $show_pending,
 145          ),
 146          'invites' => array(
 147              'id'      => 'invites',
 148              'caption' => __( 'Send Invites', 'buddypress' ),
 149              'order'   => 100,
 150              'hide'    => 1,
 151              'href'    => '#send-invites-editor',
 152          ),
 153      );
 154  
 155      if ( bp_is_active( 'friends' ) ) {
 156          $invites_nav['friends'] = array(
 157              'id'      => 'friends',
 158              'caption' => __( 'My Friends', 'buddypress' ),
 159              'order'   => 0,
 160          );
 161  
 162          if ( true === bp_nouveau_groups_disallow_all_members_invites() ) {
 163              unset( $invites_nav['members'] );
 164          }
 165      }
 166  
 167      $params['group_invites'] = array(
 168          'nav'                => bp_sort_by_key( $invites_nav, 'order', 'num' ),
 169          'loading'            => __( 'Loading members. Please wait.', 'buddypress' ),
 170          'invites_form'       => __( 'Use the "Send" button to send your invite or the "Cancel" button to abort.', 'buddypress' ),
 171          'invites_form_reset' => __( 'Group invitations cleared. Please use one of the available tabs to select members to invite.', 'buddypress' ),
 172          'invites_sending'    => __( 'Sending group invitations. Please wait.', 'buddypress' ),
 173  
 174          /* translators: %s: member name */
 175          'removeUserInvite'   => __( 'Cancel invitation %s', 'buddypress' ),
 176          'group_id'           => ! bp_get_current_group_id() ? bp_get_new_group_id() : bp_get_current_group_id(),
 177          'is_group_create'    => bp_is_group_create(),
 178          'nonces'             => array(
 179              'uninvite'     => wp_create_nonce( 'groups_invite_uninvite_user' ),
 180              'send_invites' => wp_create_nonce( 'groups_send_invites' )
 181          ),
 182      );
 183  
 184      return $params;
 185  }
 186  
 187  /**
 188   * @since 3.0.0
 189   */
 190  function bp_nouveau_groups_get_inviter_ids( $user_id, $group_id ) {
 191      if ( empty( $user_id ) || empty( $group_id ) ) {
 192          return false;
 193      }
 194  
 195      return BP_Nouveau_Group_Invite_Query::get_inviter_ids( $user_id, $group_id );
 196  }
 197  
 198  /**
 199   * @since 3.0.0
 200   */
 201  function bp_nouveau_prepare_group_potential_invites_for_js( $user ) {
 202      $bp    = buddypress();
 203      $scope = '';
 204      if ( isset( $bp->groups->invites_scope ) ) {
 205          $scope = $bp->groups->invites_scope;
 206      }
 207  
 208      $response = array(
 209          'id'      => intval( $user->ID ),
 210          'name'    => $user->display_name,
 211          'avatar'  => htmlspecialchars_decode(
 212              bp_core_fetch_avatar(
 213                  array(
 214                      'item_id' => $user->ID,
 215                      'object'  => 'user',
 216                      'type'    => 'thumb',
 217                      'width'   => 50,
 218                      'height'  => 50,
 219                      'html'    => false
 220                  )
 221              )
 222          ),
 223          'scope'      => $scope,
 224          'is_sent'    => false,
 225          'invited_by' => array(),
 226          'can_invite' => 'invited' !== $scope,
 227      );
 228  
 229      // Do extra queries only if needed
 230      if ( 'invited' === $scope ) {
 231          $response['is_sent'] = (bool) groups_check_user_has_invite( $user->ID, bp_get_current_group_id() );
 232          $inviter_ids         = bp_nouveau_groups_get_inviter_ids( $user->ID, bp_get_current_group_id() );
 233  
 234          foreach ( $inviter_ids as $inviter_id ) {
 235              $class = false;
 236  
 237              if ( bp_loggedin_user_id() === (int) $inviter_id ) {
 238                  $class = 'group-self-inviter';
 239              }
 240  
 241              $response['invited_by'][] = array(
 242                  'avatar' => htmlspecialchars_decode(
 243                      bp_core_fetch_avatar(
 244                          array(
 245                              'item_id' => $inviter_id,
 246                              'object'  => 'user',
 247                              'type'    => 'thumb',
 248                              'width'   => 50,
 249                              'height'  => 50,
 250                              'html'    => false,
 251                              'class'   => $class,
 252                          )
 253                      )
 254                  ),
 255                  'user_link' => bp_core_get_userlink( $inviter_id, false, true ),
 256                  'user_name' => bp_core_get_username( $inviter_id ),
 257              );
 258          }
 259  
 260          $response['can_edit'] = bp_is_item_admin() || in_array( bp_loggedin_user_id(), $inviter_ids, true );
 261      }
 262  
 263      /**
 264       * Filters the response value for potential group invite data for use with javascript.
 265       *
 266       * @since 3.0.0
 267       *
 268       * @param array   $response Array of invite data.
 269       * @param WP_User $user User object.
 270       */
 271      return apply_filters( 'bp_nouveau_prepare_group_potential_invites_for_js', $response, $user );
 272  }
 273  
 274  /**
 275   * @since 3.0.0
 276   */
 277  function bp_nouveau_get_group_potential_invites( $args = array() ) {
 278      $r = bp_parse_args(
 279          $args,
 280          array(
 281              'group_id'     => bp_get_current_group_id(),
 282              'type'         => 'alphabetical',
 283              'per_page'     => 20,
 284              'page'         => 1,
 285              'search_terms' => false,
 286              'member_type'  => false,
 287              'user_id'      => 0,
 288              'is_confirmed' => true,
 289          )
 290      );
 291  
 292      if ( empty( $r['group_id'] ) ) {
 293          return false;
 294      }
 295  
 296      // Check the current user's access to the group.
 297      if ( ! bp_groups_user_can_send_invites( $r['group_id'] ) ) {
 298          return false;
 299      }
 300  
 301      /*
 302       * If it's not a friend request and users can restrict invites to friends,
 303       * make sure they are not displayed in results.
 304       */
 305      if ( ! $r['user_id'] && bp_is_active( 'friends' ) && bp_is_active( 'settings' ) && ! bp_nouveau_groups_disallow_all_members_invites() ) {
 306          $r['meta_query'] = array(
 307              array(
 308                  'key'     => '_bp_nouveau_restrict_invites_to_friends',
 309                  'compare' => 'NOT EXISTS',
 310              ),
 311          );
 312      }
 313  
 314      $query = new BP_Nouveau_Group_Invite_Query( $r );
 315  
 316      $response = new stdClass();
 317  
 318      $response->meta = array( 'total_page' => 0, 'current_page' => 0 );
 319      $response->users = array();
 320  
 321      if ( ! empty( $query->results ) ) {
 322          $response->users = $query->results;
 323  
 324          if ( ! empty( $r['per_page'] ) ) {
 325              $response->meta = array(
 326                  'total_page' => ceil( (int) $query->total_users / (int) $r['per_page'] ),
 327                  'page'       => (int) $r['page'],
 328              );
 329          }
 330      }
 331  
 332      return $response;
 333  }
 334  
 335  /**
 336   * Rename the Group invite step.
 337   *
 338   * @since 3.0.0
 339   * @since 10.0.0 The function is no more creating a Group invite step.
 340   *
 341   * @param array $steps The Group create steps.
 342   * @return array       The Group create steps.
 343   */
 344  function bp_nouveau_group_invites_create_steps( $steps = array() ) {
 345      if ( isset( $steps['group-invites'] ) ) {
 346          $steps['group-invites']['name'] = _x( 'Invite', 'Group invitations menu title', 'buddypress' );
 347      }
 348  
 349      return $steps;
 350  }
 351  
 352  /**
 353   * Rename the Group Invites nav.
 354   *
 355   * @since 3.0.0
 356   * @since 10.0.0 The function is no longer creating a Group invite nav.
 357   */
 358  function bp_nouveau_group_setup_nav() {
 359      if ( ! bp_is_group() || ! bp_groups_user_can_send_invites() ) {
 360          return;
 361      }
 362  
 363      if ( bp_is_active( 'groups', 'invitations' ) ) {
 364          $bp = buddypress();
 365  
 366          $bp->groups->nav->edit_nav(
 367              array( 'name' => _x( 'Invite', 'Group invitations menu title', 'buddypress' ) ),
 368              'send-invites',
 369              bp_get_current_group_slug()
 370          );
 371      }
 372  }
 373  
 374  /**
 375   * Includes a message into the sent invitation email.
 376   *
 377   * @since 3.0.0
 378   * @deprecated 6.3.0
 379   *
 380   * @param string $message The message to send with the invite
 381   */
 382  function bp_nouveau_groups_invites_custom_message( $message = '' ) {
 383      _deprecated_function( __FUNCTION__, '6.3.0' );
 384  
 385      if ( empty( $message ) ) {
 386          return $message;
 387      }
 388  
 389      $bp = buddypress();
 390  
 391      if ( empty( $bp->groups->invites_message ) ) {
 392          return $message;
 393      }
 394  
 395      $message = str_replace( '---------------------', "
 396  ---------------------\n
 397  " . $bp->groups->invites_message . "\n
 398  ---------------------
 399      ", $message );
 400  
 401      return $message;
 402  }
 403  
 404  /**
 405   * Format a Group for a json reply
 406   *
 407   * @since 3.0.0
 408   */
 409  function bp_nouveau_prepare_group_for_js( $item ) {
 410      if ( empty( $item->id ) ) {
 411          return array();
 412      }
 413  
 414      $item_avatar_url = bp_core_fetch_avatar( array(
 415          'item_id'    => $item->id,
 416          'object'     => 'group',
 417          'type'       => 'thumb',
 418          'html'       => false
 419      ) );
 420  
 421      return array(
 422          'id'          => $item->id,
 423          'name'        => $item->name,
 424          'avatar_url'  => $item_avatar_url,
 425          'object_type' => 'group',
 426          'is_public'   => ( 'public' === $item->status ),
 427      );
 428  }
 429  
 430  /**
 431   * Group invites restriction settings navigation.
 432   *
 433   * @since 3.0.0
 434   */
 435  function bp_nouveau_groups_invites_restriction_nav() {
 436      $slug        = bp_nouveau_get_component_slug( 'settings' );
 437      $user_domain = bp_loggedin_user_domain();
 438  
 439      if ( bp_displayed_user_domain() ) {
 440          $user_domain = bp_displayed_user_domain();
 441      }
 442  
 443      bp_core_new_subnav_item( array(
 444          'name'            => _x( 'Group Invites', 'Group invitations main menu title', 'buddypress' ),
 445          'slug'            => 'invites',
 446          'parent_url'      => trailingslashit( $user_domain . $slug ),
 447          'parent_slug'     => $slug,
 448          'screen_function' => 'bp_nouveau_groups_screen_invites_restriction',
 449          'item_css_id'     => 'invites',
 450          'position'        => 70,
 451          'user_has_access' => bp_core_can_edit_settings(),
 452      ), 'members' );
 453  }
 454  
 455  /**
 456   * Group invites restriction settings Admin Bar navigation.
 457   *
 458   * @since 3.0.0
 459   *
 460   * @param array $wp_admin_nav The list of settings admin subnav items.
 461   *
 462   * @return array The list of settings admin subnav items.
 463   */
 464  function bp_nouveau_groups_invites_restriction_admin_nav( $wp_admin_nav ) {
 465      // Setup the logged in user variables.
 466      $settings_link = trailingslashit( bp_loggedin_user_domain() . bp_nouveau_get_component_slug( 'settings' ) );
 467  
 468      // Add the "Group Invites" subnav item.
 469      $wp_admin_nav[] = array(
 470          'parent' => 'my-account-' . buddypress()->settings->id,
 471          'id'     => 'my-account-' . buddypress()->settings->id . '-invites',
 472          'title'  => _x( 'Group Invites', 'Group invitations main menu title', 'buddypress' ),
 473          'href'   => trailingslashit( $settings_link . 'invites/' ),
 474      );
 475  
 476      return $wp_admin_nav;
 477  }
 478  
 479  /**
 480   * Group invites restriction screen.
 481   *
 482   * @since 3.0.0
 483   */
 484  function bp_nouveau_groups_screen_invites_restriction() {
 485      // Redirect if no invites restriction settings page is accessible.
 486      if ( 'invites' !== bp_current_action() || ! bp_is_active( 'friends' ) ) {
 487          bp_do_404();
 488          return;
 489      }
 490  
 491      if ( isset( $_POST['member-group-invites-submit'] ) ) {
 492          // Nonce check.
 493          check_admin_referer( 'bp_nouveau_group_invites_settings' );
 494  
 495          if ( bp_is_my_profile() || bp_current_user_can( 'bp_moderate' ) ) {
 496              if ( empty( $_POST['account-group-invites-preferences'] ) ) {
 497                  bp_delete_user_meta( bp_displayed_user_id(), '_bp_nouveau_restrict_invites_to_friends' );
 498              } else {
 499                  bp_update_user_meta( bp_displayed_user_id(), '_bp_nouveau_restrict_invites_to_friends', (int) $_POST['account-group-invites-preferences'] );
 500              }
 501  
 502              bp_core_add_message( __( 'Group invites preferences saved.', 'buddypress' ) );
 503          } else {
 504              bp_core_add_message( __( 'You are not allowed to perform this action.', 'buddypress' ), 'error' );
 505          }
 506  
 507          bp_core_redirect( trailingslashit( bp_displayed_user_domain() . bp_nouveau_get_component_slug( 'settings' ) ) . 'invites/' );
 508      }
 509  
 510      /**
 511       * Filters the template to load for the Group Invites settings screen.
 512       *
 513       * @since 3.0.0
 514       *
 515       * @param string $template Path to the Group Invites settings screen template to load.
 516       */
 517      bp_core_load_template( apply_filters( 'bp_nouveau_groups_screen_invites_restriction', 'members/single/settings/group-invites' ) );
 518  }
 519  
 520  /**
 521   * Makes sure the BP REST API groups/invites endpoint respects invite restrictions.
 522   *
 523   * @since 7.2.1
 524   *
 525   * @param bool|WP_Error   $retval  Whether the request can continue.
 526   * @param WP_REST_Request $request The request sent to the API.
 527   * @return bool|WP_Error
 528   */
 529  function bp_nouveau_restrict_rest_group_invite_to_friends( $retval, $request ) {
 530      if ( true === $retval && bp_is_active( 'friends' ) ) {
 531          $group_id   = $request->get_param( 'group_id' );
 532          $user_id    = $request->get_param( 'user_id' );
 533          $inviter_id = $request->get_param( 'inviter_id' );
 534  
 535          if ( ! $inviter_id ) {
 536              $inviter_id = bp_loggedin_user_id();
 537          }
 538  
 539          if ( bp_nouveau_groups_get_group_invites_setting( $user_id ) && 'is_friend' !== BP_Friends_Friendship::check_is_friend( $inviter_id, $user_id ) ) {
 540              $retval = new WP_Error(
 541                  'bp_rest_group_invite_cannot_create_item',
 542                  __( 'Sorry, you are not allowed to create the invitation as requested.', 'buddypress' ),
 543                  array(
 544                      'status' => rest_authorization_required_code(),
 545                  )
 546              );
 547          }
 548      }
 549  
 550      return $retval;
 551  }
 552  add_filter( 'bp_rest_group_invites_create_item_permissions_check', 'bp_nouveau_restrict_rest_group_invite_to_friends', 10, 2 );
 553  
 554  /**
 555   * @since 3.0.0
 556   */
 557  function bp_nouveau_get_groups_directory_nav_items() {
 558      $nav_items = array();
 559  
 560      $nav_items['all'] = array(
 561          'component' => 'groups',
 562          'slug'      => 'all', // slug is used because BP_Core_Nav requires it, but it's the scope
 563          'li_class'  => array( 'selected' ),
 564          'link'      => bp_get_groups_directory_permalink(),
 565          'text'      => __( 'All Groups', 'buddypress' ),
 566          'count'     => bp_get_total_group_count(),
 567          'position'  => 5,
 568      );
 569  
 570      if ( is_user_logged_in() ) {
 571  
 572          $my_groups_count = bp_get_total_group_count_for_user( bp_loggedin_user_id() );
 573  
 574          // If the user has groups create a nav item
 575          if ( $my_groups_count ) {
 576              $nav_items['personal'] = array(
 577                  'component' => 'groups',
 578                  'slug'      => 'personal', // slug is used because BP_Core_Nav requires it, but it's the scope
 579                  'li_class'  => array(),
 580                  'link'      => bp_loggedin_user_domain() . bp_nouveau_get_component_slug( 'groups' ) . '/my-groups/',
 581                  'text'      => __( 'My Groups', 'buddypress' ),
 582                  'count'     => $my_groups_count,
 583                  'position'  => 15,
 584              );
 585          }
 586  
 587          // If the user can create groups, add the create nav
 588          if ( bp_user_can_create_groups() ) {
 589              $nav_items['create'] = array(
 590                  'component' => 'groups',
 591                  'slug'      => 'create', // slug is used because BP_Core_Nav requires it, but it's the scope
 592                  'li_class'  => array( 'no-ajax', 'group-create', 'create-button' ),
 593                  'link'      => trailingslashit( bp_get_groups_directory_permalink() . 'create' ),
 594                  'text'      => __( 'Create a Group', 'buddypress' ),
 595                  'count'     => false,
 596                  'position'  => 999,
 597              );
 598          }
 599      }
 600  
 601      // Check for the deprecated hook :
 602      $extra_nav_items = bp_nouveau_parse_hooked_dir_nav( 'bp_groups_directory_group_filter', 'groups', 20 );
 603  
 604      if ( ! empty( $extra_nav_items ) ) {
 605          $nav_items = array_merge( $nav_items, $extra_nav_items );
 606      }
 607  
 608      /**
 609       * Use this filter to introduce your custom nav items for the groups directory.
 610       *
 611       * @since 3.0.0
 612       *
 613       * @param  array $nav_items The list of the groups directory nav items.
 614       */
 615      return apply_filters( 'bp_nouveau_get_groups_directory_nav_items', $nav_items );
 616  }
 617  
 618  /**
 619   * Get Dropdown filters for the groups component
 620   *
 621   * @since 3.0.0
 622   *
 623   * @param string $context 'directory' or 'user'
 624   *
 625   * @return array the filters
 626   */
 627  function bp_nouveau_get_groups_filters( $context = '' ) {
 628      if ( empty( $context ) ) {
 629          return array();
 630      }
 631  
 632      $action = '';
 633      if ( 'user' === $context ) {
 634          $action = 'bp_member_group_order_options';
 635      } elseif ( 'directory' === $context ) {
 636          $action = 'bp_groups_directory_order_options';
 637      }
 638  
 639      /**
 640       * Recommended, filter here instead of adding an action to 'bp_member_group_order_options'
 641       * or 'bp_groups_directory_order_options'
 642       *
 643       * @since 3.0.0
 644       *
 645       * @param array  the members filters.
 646       * @param string the context.
 647       */
 648      $filters = apply_filters( 'bp_nouveau_get_groups_filters', array(
 649          'active'       => __( 'Last Active', 'buddypress' ),
 650          'popular'      => __( 'Most Members', 'buddypress' ),
 651          'newest'       => __( 'Newly Created', 'buddypress' ),
 652          'alphabetical' => __( 'Alphabetical', 'buddypress' ),
 653      ), $context );
 654  
 655      if ( $action ) {
 656          return bp_nouveau_parse_hooked_options( $action, $filters );
 657      }
 658  
 659      return $filters;
 660  }
 661  
 662  /**
 663   * Catch the arguments for buttons
 664   *
 665   * @since 3.0.0
 666   *
 667   * @param array $button The arguments of the button that BuddyPress is about to create.
 668   *
 669   * @return array An empty array to stop the button creation process.
 670   */
 671  function bp_nouveau_groups_catch_button_args( $button = array() ) {
 672      /**
 673       * Globalize the arguments so that we can use it
 674       * in bp_nouveau_get_groups_buttons().
 675       */
 676      bp_nouveau()->groups->button_args = $button;
 677  
 678      // return an empty array to stop the button creation process
 679      return array();
 680  }
 681  
 682  /**
 683   * Catch the content hooked to the 'bp_group_header_meta' action
 684   *
 685   * @since 3.0.0
 686   *
 687   * @return string|bool HTML Output if hooked. False otherwise.
 688   */
 689  function bp_nouveau_get_hooked_group_meta() {
 690      ob_start();
 691  
 692      /**
 693       * Fires after inside the group header item meta section.
 694       *
 695       * @since 1.2.0
 696       */
 697      do_action( 'bp_group_header_meta' );
 698  
 699      $output = ob_get_clean();
 700  
 701      if ( ! empty( $output ) ) {
 702          return $output;
 703      }
 704  
 705      return false;
 706  }
 707  
 708  /**
 709   * Display the Widgets of Group extensions into the default front page?
 710   *
 711   * @since 3.0.0
 712   *
 713   * @return bool True to display. False otherwise.
 714   */
 715  function bp_nouveau_groups_do_group_boxes() {
 716      $group_settings = bp_nouveau_get_appearance_settings();
 717  
 718      return ! empty( $group_settings['group_front_page'] ) && ! empty( $group_settings['group_front_boxes'] );
 719  }
 720  
 721  /**
 722   * Display description of the Group into the default front page?
 723   *
 724   * @since 3.0.0
 725   *
 726   * @return bool True to display. False otherwise.
 727   */
 728  function bp_nouveau_groups_front_page_description() {
 729      $group_settings = bp_nouveau_get_appearance_settings();
 730  
 731      // This check is a problem it needs to be used in templates but returns true even if not on the front page
 732      // return false on this if we are not displaying the front page 'bp_is_group_home()'
 733      // This may well be a bad approach to re-think ~hnla.
 734      // @todo
 735      return ! empty( $group_settings['group_front_page'] ) && ! empty( $group_settings['group_front_description'] ) && bp_is_group_home();
 736  }
 737  
 738  /**
 739   * Add sections to the customizer for the groups component.
 740   *
 741   * @since 3.0.0
 742   *
 743   * @param array $sections the Customizer sections to add.
 744   *
 745   * @return array the Customizer sections to add.
 746   */
 747  function bp_nouveau_groups_customizer_sections( $sections = array() ) {
 748      return array_merge( $sections, array(
 749          'bp_nouveau_group_front_page' => array(
 750              'title'       => __( 'Group front page', 'buddypress' ),
 751              'panel'       => 'bp_nouveau_panel',
 752              'priority'    => 20,
 753              'description' => __( 'Configure the default front page for groups.', 'buddypress' ),
 754          ),
 755          'bp_nouveau_group_primary_nav' => array(
 756              'title'       => __( 'Group navigation', 'buddypress' ),
 757              'panel'       => 'bp_nouveau_panel',
 758              'priority'    => 40,
 759              'description' => __( 'Customize the navigation menu for groups. See your changes by navigating to a group in the live-preview window.', 'buddypress' ),
 760          ),
 761      ) );
 762  }
 763  
 764  /**
 765   * Add settings to the customizer for the groups component.
 766   *
 767   * @since 3.0.0
 768   *
 769   * @param array $settings Optional. The settings to add.
 770   *
 771   * @return array the settings to add.
 772   */
 773  function bp_nouveau_groups_customizer_settings( $settings = array() ) {
 774      return array_merge( $settings, array(
 775          'bp_nouveau_appearance[group_front_page]' => array(
 776              'index'             => 'group_front_page',
 777              'capability'        => 'bp_moderate',
 778              'sanitize_callback' => 'absint',
 779              'transport'         => 'refresh',
 780              'type'              => 'option',
 781          ),
 782          'bp_nouveau_appearance[group_front_boxes]' => array(
 783              'index'             => 'group_front_boxes',
 784              'capability'        => 'bp_moderate',
 785              'sanitize_callback' => 'absint',
 786              'transport'         => 'refresh',
 787              'type'              => 'option',
 788          ),
 789          'bp_nouveau_appearance[group_front_description]' => array(
 790              'index'             => 'group_front_description',
 791              'capability'        => 'bp_moderate',
 792              'sanitize_callback' => 'absint',
 793              'transport'         => 'refresh',
 794              'type'              => 'option',
 795          ),
 796          'bp_nouveau_appearance[group_nav_display]' => array(
 797              'index'             => 'group_nav_display',
 798              'capability'        => 'bp_moderate',
 799              'sanitize_callback' => 'absint',
 800              'transport'         => 'refresh',
 801              'type'              => 'option',
 802          ),
 803          'bp_nouveau_appearance[group_nav_tabs]' => array(
 804              'index'             => 'group_nav_tabs',
 805              'capability'        => 'bp_moderate',
 806              'sanitize_callback' => 'absint',
 807              'transport'         => 'refresh',
 808              'type'              => 'option',
 809          ),
 810          'bp_nouveau_appearance[group_subnav_tabs]' => array(
 811              'index'             => 'group_subnav_tabs',
 812              'capability'        => 'bp_moderate',
 813              'sanitize_callback' => 'absint',
 814              'transport'         => 'refresh',
 815              'type'              => 'option',
 816          ),
 817          'bp_nouveau_appearance[groups_create_tabs]' => array(
 818              'index'             => 'groups_create_tabs',
 819              'capability'        => 'bp_moderate',
 820              'sanitize_callback' => 'absint',
 821              'transport'         => 'refresh',
 822              'type'              => 'option',
 823          ),
 824          'bp_nouveau_appearance[group_nav_order]' => array(
 825              'index'             => 'group_nav_order',
 826              'capability'        => 'bp_moderate',
 827              'sanitize_callback' => 'bp_nouveau_sanitize_nav_order',
 828              'transport'         => 'refresh',
 829              'type'              => 'option',
 830          ),
 831          'bp_nouveau_appearance[groups_layout]' => array(
 832              'index'             => 'groups_layout',
 833              'capability'        => 'bp_moderate',
 834              'sanitize_callback' => 'absint',
 835              'transport'         => 'refresh',
 836              'type'              => 'option',
 837          ),
 838          'bp_nouveau_appearance[groups_dir_tabs]' => array(
 839              'index'             => 'groups_dir_tabs',
 840              'capability'        => 'bp_moderate',
 841              'sanitize_callback' => 'absint',
 842              'transport'         => 'refresh',
 843              'type'              => 'option',
 844          ),
 845      ) );
 846  }
 847  
 848  /**
 849   * Add controls for the settings of the customizer for the groups component.
 850   *
 851   * @since 3.0.0
 852   *
 853   * @param array $controls Optional. The controls to add.
 854   *
 855   * @return array the controls to add.
 856   */
 857  function bp_nouveau_groups_customizer_controls( $controls = array() ) {
 858      return array_merge( $controls, array(
 859          'group_front_page' => array(
 860              'label'      => __( 'Enable custom front pages for groups.', 'buddypress' ),
 861              'section'    => 'bp_nouveau_group_front_page',
 862              'settings'   => 'bp_nouveau_appearance[group_front_page]',
 863              'type'       => 'checkbox',
 864          ),
 865          'group_front_boxes' => array(
 866              'label'      => __( 'Enable custom boxes for group homepages. When enabled, Plugins using the BuddyPress Group Extension API can include content into these boxes.', 'buddypress' ),
 867              'section'    => 'bp_nouveau_group_front_page',
 868              'settings'   => 'bp_nouveau_appearance[group_front_boxes]',
 869              'type'       => 'checkbox',
 870          ),
 871          'group_front_description' => array(
 872              'label'      => __( "Display the group description in the body of the group's front page.", 'buddypress' ),
 873              'section'    => 'bp_nouveau_group_front_page',
 874              'settings'   => 'bp_nouveau_appearance[group_front_description]',
 875              'type'       => 'checkbox',
 876          ),
 877          'group_nav_display' => array(
 878              'label'      => __( 'Display the group navigation vertically.', 'buddypress' ),
 879              'section'    => 'bp_nouveau_group_primary_nav',
 880              'settings'   => 'bp_nouveau_appearance[group_nav_display]',
 881              'type'       => 'checkbox',
 882          ),
 883          'group_nav_tabs' => array(
 884              'label'      => __( 'Use tab styling for primary navigation.', 'buddypress' ),
 885              'section'    => 'bp_nouveau_group_primary_nav',
 886              'settings'   => 'bp_nouveau_appearance[group_nav_tabs]',
 887              'type'       => 'checkbox',
 888          ),
 889          'group_subnav_tabs' => array(
 890              'label'      => __( 'Use tab styling for secondary navigation.', 'buddypress' ),
 891              'section'    => 'bp_nouveau_group_primary_nav',
 892              'settings'   => 'bp_nouveau_appearance[group_subnav_tabs]',
 893              'type'       => 'checkbox',
 894          ),
 895          'groups_create_tabs' => array(
 896              'label'      => __( 'Use tab styling for the group creation process.', 'buddypress' ),
 897              'section'    => 'bp_nouveau_group_primary_nav',
 898              'settings'   => 'bp_nouveau_appearance[groups_create_tabs]',
 899              'type'       => 'checkbox',
 900          ),
 901          'group_nav_order' => array(
 902              'class'       => 'BP_Nouveau_Nav_Customize_Control',
 903              'label'      => __( 'Reorder the primary navigation for a group.', 'buddypress' ),
 904              'section'    => 'bp_nouveau_group_primary_nav',
 905              'settings'   => 'bp_nouveau_appearance[group_nav_order]',
 906              'type'       => 'group',
 907          ),
 908          'groups_layout' => array(
 909              'label'      => _x( 'Groups', 'Customizer control label', 'buddypress' ),
 910              'section'    => 'bp_nouveau_loops_layout',
 911              'settings'   => 'bp_nouveau_appearance[groups_layout]',
 912              'type'       => 'select',
 913              'choices'    => bp_nouveau_customizer_grid_choices(),
 914          ),
 915          'members_group_layout' => array(
 916              'label'      => __( 'Group > Members', 'buddypress' ),
 917              'section'    => 'bp_nouveau_loops_layout',
 918              'settings'   => 'bp_nouveau_appearance[members_group_layout]',
 919              'type'       => 'select',
 920              'choices'    => bp_nouveau_customizer_grid_choices(),
 921          ),
 922          'group_dir_layout' => array(
 923              'label'      => __( 'Use column navigation for the Groups directory.', 'buddypress' ),
 924              'section'    => 'bp_nouveau_dir_layout',
 925              'settings'   => 'bp_nouveau_appearance[groups_dir_layout]',
 926              'type'       => 'checkbox',
 927          ),
 928          'group_dir_tabs' => array(
 929              'label'      => __( 'Use tab styling for Groups directory navigation.', 'buddypress' ),
 930              'section'    => 'bp_nouveau_dir_layout',
 931              'settings'   => 'bp_nouveau_appearance[groups_dir_tabs]',
 932              'type'       => 'checkbox',
 933          ),
 934      ) );
 935  }
 936  
 937  /**
 938   * Add the default group front template to the front template hierarchy.
 939   *
 940   * @since 3.0.0
 941   *
 942   * @param array           $templates Optional. The list of templates for the front.php template part.
 943   * @param BP_Groups_Group $group Optional. The group object.
 944   *
 945   * @return array The same list with the default front template if needed.
 946   */
 947  function bp_nouveau_group_reset_front_template( $templates = array(), $group = null ) {
 948      if ( empty( $group->id ) ) {
 949          return $templates;
 950      }
 951  
 952      $use_default_front = bp_nouveau_get_appearance_settings( 'group_front_page' );
 953  
 954      // Setting the front template happens too early, so we need this!
 955      if ( is_customize_preview() ) {
 956          $use_default_front = bp_nouveau_get_temporary_setting( 'group_front_page', $use_default_front );
 957      }
 958  
 959      if ( ! empty( $use_default_front ) ) {
 960          array_push( $templates, 'groups/single/default-front.php' );
 961      }
 962  
 963      /**
 964       * Filters the BuddyPress Nouveau template hierarchy after resetting front template for groups.
 965       *
 966       * @since 3.0.0
 967       *
 968       * @param array $templates Array of templates.
 969       */
 970      return apply_filters( '_bp_nouveau_group_reset_front_template', $templates );
 971  }
 972  
 973  /**
 974   * Locate a single group template into a specific hierarchy.
 975   *
 976   * @since 3.0.0
 977   *
 978   * @param string $template Optional. The template part to get (eg: activity, members...).
 979   *
 980   * @return string The located template.
 981   */
 982  function bp_nouveau_group_locate_template_part( $template = '' ) {
 983      $current_group = groups_get_current_group();
 984      $bp_nouveau    = bp_nouveau();
 985  
 986      if ( ! $template || empty( $current_group->id ) ) {
 987          return '';
 988      }
 989  
 990      // Use a global to avoid requesting the hierarchy for each template
 991      if ( ! isset( $bp_nouveau->groups->current_group_hierarchy ) ) {
 992          $bp_nouveau->groups->current_group_hierarchy = array(
 993              'groups/single/%s-id-' . (int) $current_group->id                     . '.php',
 994              'groups/single/%s-slug-' . sanitize_file_name( $current_group->slug ) . '.php',
 995          );
 996  
 997          /**
 998           * Check for group types and add it to the hierarchy
 999           */
1000          if ( bp_groups_get_group_types() ) {
1001              $current_group_type = bp_groups_get_group_type( $current_group->id );
1002              if ( ! $current_group_type ) {
1003                  $current_group_type = 'none';
1004              }
1005  
1006              $bp_nouveau->groups->current_group_hierarchy[] = 'groups/single/%s-group-type-' . sanitize_file_name( $current_group_type ) . '.php';
1007          }
1008  
1009          $bp_nouveau->groups->current_group_hierarchy = array_merge( $bp_nouveau->groups->current_group_hierarchy, array(
1010              'groups/single/%s-status-' . sanitize_file_name( $current_group->status ) . '.php',
1011              'groups/single/%s.php'
1012          ) );
1013      }
1014  
1015      // Init the templates
1016      $templates = array();
1017  
1018      // Loop in the hierarchy to fill it for the requested template part
1019      foreach ( $bp_nouveau->groups->current_group_hierarchy as $part ) {
1020          $templates[] = sprintf( $part, sanitize_file_name( $template ) );
1021      }
1022  
1023      /**
1024       * Filters the found template parts for the group template part locating functionality.
1025       *
1026       * @since 3.0.0
1027       *
1028       * @param array $templates Array of found templates.
1029       */
1030      return bp_locate_template( apply_filters( 'bp_nouveau_group_locate_template_part', $templates ), false, true );
1031  }
1032  
1033  /**
1034   * Load a single group template part
1035   *
1036   * @since 3.0.0
1037   *
1038   * @param string $template Optional. The template part to get (eg: activity, members...).
1039   *
1040   * @return string HTML output.
1041   */
1042  function bp_nouveau_group_get_template_part( $template = '' ) {
1043      $located = bp_nouveau_group_locate_template_part( $template );
1044  
1045      if ( false !== $located ) {
1046          $slug = str_replace( '.php', '', $located );
1047          $name = null;
1048  
1049          /**
1050           * Let plugins adding an action to bp_get_template_part get it from here.
1051           *
1052           * This is a variable hook that is dependent on the template part slug.
1053           *
1054           * @since 3.0.0
1055           *
1056           * @param string $slug Template part slug requested.
1057           * @param string $name Template part name requested.
1058           */
1059          do_action( 'get_template_part_' . $slug, $slug, $name );
1060  
1061          load_template( $located, true );
1062      }
1063  
1064      return $located;
1065  }
1066  
1067  /**
1068   * Are we inside the Current group's default front page sidebar?
1069   *
1070   * @since 3.0.0
1071   *
1072   * @return bool True if in the group's home sidebar. False otherwise.
1073   */
1074  function bp_nouveau_group_is_home_widgets() {
1075      return ( true === bp_nouveau()->groups->is_group_home_sidebar );
1076  }
1077  
1078  /**
1079   * Filter the Latest activities Widget to only keep the one of the group displayed
1080   *
1081   * @since 3.0.0
1082   *
1083   * @param array $args Optional. The Activities Template arguments.
1084   *
1085   * @return array The Activities Template arguments.
1086   */
1087  function bp_nouveau_group_activity_widget_overrides( $args = array() ) {
1088      return array_merge( $args, array(
1089          'object'     => 'groups',
1090          'primary_id' => bp_get_current_group_id(),
1091      ) );
1092  }
1093  
1094  /**
1095   * Filter the Groups widget to only keep the displayed group.
1096   *
1097   * @since 3.0.0
1098   *
1099   * @param array $args Optional. The Groups Template arguments.
1100   *
1101   * @return array The Groups Template arguments.
1102   */
1103  function bp_nouveau_group_groups_widget_overrides( $args = array() ) {
1104      return array_merge( $args, array(
1105          'include' => bp_get_current_group_id(),
1106      ) );
1107  }
1108  
1109  /**
1110   * Filter the Members widgets to only keep members of the displayed group.
1111   *
1112   * @since 3.0.0
1113   *
1114   * @param array $args Optional. The Members Template arguments.
1115   *
1116   * @return array The Members Template arguments.
1117   */
1118  function bp_nouveau_group_members_widget_overrides( $args = array() ) {
1119      $group_members = groups_get_group_members( array( 'exclude_admins_mods' => false ) );
1120  
1121      if ( empty( $group_members['members'] ) ) {
1122          return $args;
1123      }
1124  
1125      return array_merge( $args, array(
1126          'include' => wp_list_pluck( $group_members['members'], 'ID' ),
1127      ) );
1128  }
1129  
1130  /**
1131   * Init the Group's default front page filters as we're in the sidebar
1132   *
1133   * @since 3.0.0
1134   */
1135  function bp_nouveau_groups_add_home_widget_filters() {
1136      add_filter( 'bp_nouveau_activity_widget_query', 'bp_nouveau_group_activity_widget_overrides', 10, 1 );
1137      add_filter( 'bp_before_has_groups_parse_args', 'bp_nouveau_group_groups_widget_overrides', 10, 1 );
1138      add_filter( 'bp_before_has_members_parse_args', 'bp_nouveau_group_members_widget_overrides', 10, 1 );
1139  
1140      /**
1141       * Fires after BuddyPress Nouveau groups have added their home widget filters.
1142       *
1143       * @since 3.0.0
1144       */
1145      do_action( 'bp_nouveau_groups_add_home_widget_filters' );
1146  }
1147  
1148  /**
1149   * Remove the Group's default front page filters as we're no more in the sidebar
1150   *
1151   * @since 3.0.0
1152   */
1153  function bp_nouveau_groups_remove_home_widget_filters() {
1154      remove_filter( 'bp_nouveau_activity_widget_query', 'bp_nouveau_group_activity_widget_overrides', 10, 1 );
1155      remove_filter( 'bp_before_has_groups_parse_args', 'bp_nouveau_group_groups_widget_overrides', 10, 1 );
1156      remove_filter( 'bp_before_has_members_parse_args', 'bp_nouveau_group_members_widget_overrides', 10, 1 );
1157  
1158      /**
1159       * Fires after BuddyPress Nouveau groups have removed their home widget filters.
1160       *
1161       * @since 3.0.0
1162       */
1163      do_action( 'bp_nouveau_groups_remove_home_widget_filters' );
1164  }
1165  
1166  /**
1167   * Get the hook, nonce, and eventually a specific template for Core Group's create screens.
1168   *
1169   * @since 3.0.0
1170   *
1171   * @param string $id Optional. The screen id
1172   *
1173   * @return mixed An array containing the hook dynamic part, the nonce, and eventually a specific template.
1174   *               False if it's not a core create screen.
1175   */
1176  function bp_nouveau_group_get_core_create_screens( $id = '' ) {
1177      // screen id => dynamic part of the hooks, nonce & specific template to use.
1178      $screens = array(
1179          'group-details' => array(
1180              'hook'     => 'group_details_creation_step',
1181              'nonce'    => 'groups_create_save_group-details',
1182              'template' => 'groups/single/admin/edit-details',
1183          ),
1184          'group-settings' => array(
1185              'hook'  => 'group_settings_creation_step',
1186              'nonce' => 'groups_create_save_group-settings',
1187          ),
1188          'group-avatar' => array(
1189              'hook'  => 'group_avatar_creation_step',
1190              'nonce' => 'groups_create_save_group-avatar',
1191          ),
1192          'group-cover-image' => array(
1193              'hook'  => 'group_cover_image_creation_step',
1194              'nonce' => 'groups_create_save_group-cover-image',
1195          ),
1196          'group-invites' => array(
1197              'hook'     => 'group_invites_creation_step',
1198              'nonce'    => 'groups_create_save_group-invites',
1199              'template' => 'common/js-templates/invites/index',
1200          ),
1201      );
1202  
1203      if ( isset( $screens[ $id ] ) ) {
1204          return $screens[ $id ];
1205      }
1206  
1207      return false;
1208  }
1209  
1210  /**
1211   * Get the hook and nonce for Core Group's manage screens.
1212   *
1213   * @since 3.0.0
1214   *
1215   * @param string $id Optional. The screen id
1216   *
1217   * @return mixed An array containing the hook dynamic part and the nonce.
1218   *               False if it's not a core manage screen.
1219   */
1220  function bp_nouveau_group_get_core_manage_screens( $id = '' ) {
1221      // screen id => dynamic part of the hooks & nonce.
1222      $screens = array(
1223          'edit-details'        => array( 'hook' => 'group_details_admin',             'nonce' => 'groups_edit_group_details'  ),
1224          'group-settings'      => array( 'hook' => 'group_settings_admin',            'nonce' => 'groups_edit_group_settings' ),
1225          'group-avatar'        => array( 'hook' => 'group_settings_avatar',           'nonce' => ''                           ),
1226          'group-cover-image'   => array( 'hook' => 'group_settings_cover_image',      'nonce' => ''                           ),
1227          'manage-members'      => array( 'hook' => 'group_manage_members_admin',      'nonce' => ''                           ),
1228          'membership-requests' => array( 'hook' => 'group_membership_requests_admin', 'nonce' => ''                           ),
1229          'delete-group'        => array( 'hook' => 'group_delete_admin',              'nonce' => 'groups_delete_group'        ),
1230      );
1231  
1232      if ( isset( $screens[ $id ] ) ) {
1233          return $screens[ $id ];
1234      }
1235  
1236      return false;
1237  }
1238  
1239  /**
1240   * Register notifications filters for the groups component.
1241   *
1242   * @since 3.0.0
1243   */
1244  function bp_nouveau_groups_notification_filters() {
1245      $notifications = array(
1246          array(
1247              'id'       => 'new_membership_request',
1248              'label'    => __( 'Pending Group membership requests', 'buddypress' ),
1249              'position' => 55,
1250          ),
1251          array(
1252              'id'       => 'membership_request_accepted',
1253              'label'    => __( 'Accepted Group membership requests', 'buddypress' ),
1254              'position' => 65,
1255          ),
1256          array(
1257              'id'       => 'membership_request_rejected',
1258              'label'    => __( 'Rejected Group membership requests', 'buddypress' ),
1259              'position' => 75,
1260          ),
1261          array(
1262              'id'       => 'member_promoted_to_admin',
1263              'label'    => __( 'Group Administrator promotions', 'buddypress' ),
1264              'position' => 85,
1265          ),
1266          array(
1267              'id'       => 'member_promoted_to_mod',
1268              'label'    => __( 'Group Moderator promotions', 'buddypress' ),
1269              'position' => 95,
1270          ),
1271          array(
1272              'id'       => 'group_invite',
1273              'label'    => __( 'Group invitations', 'buddypress' ),
1274              'position' => 105,
1275          ),
1276      );
1277  
1278      foreach ( $notifications as $notification ) {
1279          bp_nouveau_notifications_register_filter( $notification );
1280      }
1281  }
1282  
1283  /**
1284   * Makes sure the Nouveau specific behavior about Group invites visibility is applied to the REST API.
1285   *
1286   * @since 7.2.1
1287   *
1288   * @param true|WP_Error   $retval  Whether the current user can list invites.
1289   * @param WP_REST_Request $request The request sent to the API.
1290   * @return true|WP_Error Whether the current user can list invites.
1291   */
1292  function bp_nouveau_rest_group_invites_get_items_permissions_check( $retval, $request ) {
1293      if ( is_wp_error( $retval ) ) {
1294          $group_id = (int) $request['group_id'];
1295  
1296          if ( groups_is_user_member( bp_loggedin_user_id(), $group_id ) ) {
1297              $retval = true;
1298          }
1299      }
1300  
1301      return $retval;
1302  }
1303  add_filter( 'bp_rest_group_invites_get_items_permissions_check', 'bp_nouveau_rest_group_invites_get_items_permissions_check', 10, 2 );


Generated: Thu Nov 21 01:00:57 2024 Cross-referenced by PHPXref 0.7.1