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


Generated: Tue Oct 26 01:00:55 2021 Cross-referenced by PHPXref 0.7.1