Skip to:
Content

BuddyPress.org

Ticket #6210: 6210.03072019.diff

File 6210.03072019.diff, 173.2 KB (added by dcavins, 6 years ago)

Add core invitations classes and groups invitations extension class. Update tests.

  • src/bp-core/admin/bp-core-admin-schema.php

    diff --git src/bp-core/admin/bp-core-admin-schema.php src/bp-core/admin/bp-core-admin-schema.php
    index 02a410ba9..f4d5b9e4c 100644
    function bp_core_install_emails() { 
    535535         */
    536536        do_action( 'bp_core_install_emails' );
    537537}
     538
     539/**
     540 * Install database tables for the Invitations API
     541 *
     542 * @since 5.0.0
     543 *
     544 * @uses bp_core_set_charset()
     545 * @uses bp_core_get_table_prefix()
     546 * @uses dbDelta()
     547 */
     548function bp_core_install_invitations() {
     549        $sql             = array();
     550        $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
     551        $bp_prefix       = bp_core_get_table_prefix();
     552        $sql[] = "CREATE TABLE {$bp_prefix}bp_invitations (
     553                id bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
     554                user_id bigint(20) NOT NULL,
     555                inviter_id bigint(20) NOT NULL,
     556                invitee_email varchar(100) DEFAULT NULL,
     557                component_name varchar(75) NOT NULL,
     558                component_action varchar(75) NOT NULL,
     559                item_id bigint(20) NOT NULL,
     560                secondary_item_id bigint(20) DEFAULT NULL,
     561                type varchar(12) NOT NULL DEFAULT 'invite',
     562                content longtext DEFAULT '',
     563                date_modified datetime NOT NULL,
     564                invite_sent tinyint(1) NOT NULL DEFAULT '0',
     565                accepted tinyint(1) NOT NULL DEFAULT '0',
     566                KEY user_id (user_id),
     567                KEY inviter_id (inviter_id),
     568                KEY invitee_email (invitee_email),
     569                KEY component_name (component_name),
     570                KEY component_action (component_action),
     571                KEY item_id (item_id),
     572                KEY secondary_item_id (secondary_item_id),
     573                KEY type (type),
     574                KEY invite_sent (invite_sent),
     575                KEY accepted (accepted)
     576                ) {$charset_collate};";
     577        dbDelta( $sql );
     578
     579        // @TODO: Migrate invitations here
     580
     581        /**
     582         * Fires after BuddyPress adds the invitations table.
     583         *
     584         * @since 5.0.0
     585         */
     586        do_action( 'bp_core_install_invitations' );
     587}
  • src/bp-core/bp-core-functions.php

    diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
    index f3c8be614..dfeb65368 100644
    function bp_email_get_schema() { 
    34793479                        /* translators: do not remove {} brackets or translate its contents. */
    34803480                        'post_title'   => __( '[{{{site.name}}}] You have an invitation to the group: "{{group.name}}"', 'buddypress' ),
    34813481                        /* translators: do not remove {} brackets or translate its contents. */
    3482                         'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: &quot;{{group.name}}&quot;.\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ),
     3482                        'post_content' => __( "<a href=\"{{{inviter.url}}}\">{{inviter.name}}</a> has invited you to join the group: &quot;{{group.name}}&quot;.\n{{invite.message}}\n<a href=\"{{{invites.url}}}\">Go here to accept your invitation</a> or <a href=\"{{{group.url}}}\">visit the group</a> to learn more.", 'buddypress' ),
    34833483                        /* translators: do not remove {} brackets or translate its contents. */
    34843484                        'post_excerpt' => __( "{{inviter.name}} has invited you to join the group: \"{{group.name}}\".\n\nTo accept your invitation, visit: {{{invites.url}}}\n\nTo learn more about the group, visit: {{{group.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ),
    34853485                ),
    function bp_email_get_schema() { 
    34953495                        /* translators: do not remove {} brackets or translate its contents. */
    34963496                        'post_title'   => __( '[{{{site.name}}}] Membership request for group: {{group.name}}', 'buddypress' ),
    34973497                        /* translators: do not remove {} brackets or translate its contents. */
    3498                         'post_content' => __( "<a href=\"{{{profile.url}}}\">{{requesting-user.name}}</a> wants to join the group &quot;{{group.name}}&quot;. As you are an administrator of this group, you must either accept or reject the membership request.\n\n<a href=\"{{{group-requests.url}}}\">Go here to manage this</a> and all other pending requests.", 'buddypress' ),
     3498                        'post_content' => __( "<a href=\"{{{profile.url}}}\">{{requesting-user.name}}</a> wants to join the group &quot;{{group.name}}&quot;.\n {{request.message}}\n As you are an administrator of this group, you must either accept or reject the membership request.\n\n<a href=\"{{{group-requests.url}}}\">Go here to manage this</a> and all other pending requests.", 'buddypress' ),
    34993499                        /* translators: do not remove {} brackets or translate its contents. */
    35003500                        'post_excerpt' => __( "{{requesting-user.name}} wants to join the group \"{{group.name}}\". As you are the administrator of this group, you must either accept or reject the membership request.\n\nTo manage this and all other pending requests, visit: {{{group-requests.url}}}\n\nTo view {{requesting-user.name}}'s profile, visit: {{{profile.url}}}", 'buddypress' ),
    35013501                ),
  • new file src/bp-core/bp-core-invitations-cache.php

    diff --git src/bp-core/bp-core-invitations-cache.php src/bp-core/bp-core-invitations-cache.php
    new file mode 100644
    index 000000000..7cf867398
    - +  
     1<?php
     2/**
     3 * BuddyPress Invitation Caching Functions.
     4 *
     5 * Caching functions handle the clearing of cached objects and pages on specific
     6 * actions throughout BuddyPress.
     7 *
     8 * @package BuddyPress
     9 * @subpackage InvitationsCache
     10 * @since 5.0.0
     11 */
     12
     13/**
     14 * Resets all incremented bp_invitations caches.
     15 *
     16 * @since 5.0.0
     17 */
     18function bp_invitations_reset_cache_incrementor() {
     19        bp_core_reset_incrementor( 'bp_invitations' );
     20}
     21add_action( 'bp_invitation_after_save', 'bp_invitations_reset_cache_incrementor' );
     22add_action( 'bp_invitation_after_delete', 'bp_invitations_reset_cache_incrementor' );
  • src/bp-core/bp-core-update.php

    diff --git src/bp-core/bp-core-update.php src/bp-core/bp-core-update.php
    index b006ff4d5..4a4b1e20a 100644
    function bp_version_updater() { 
    211211                bp_update_option( 'bp-active-components', $default_components );
    212212                bp_core_add_page_mappings( $default_components, 'delete' );
    213213                bp_core_install_emails();
     214                bp_core_install_invitations();
    214215
    215216        // Upgrades.
    216217        } else {
    function bp_version_updater() { 
    268269                if ( $raw_db_version < 11105 ) {
    269270                        bp_update_to_2_7();
    270271                }
     272
     273                // Version 5.0.0.
     274                if ( $raw_db_version < 11300 ) {
     275                        bp_update_to_5_0();
     276                }
    271277        }
    272278
    273279        /* All done! *************************************************************/
    function bp_update_to_2_7() { 
    542548        bp_add_option( '_bp_ignore_deprecated_code', false );
    543549}
    544550
     551/**
     552 * 5.0.0 update routine.
     553 *
     554 * - Create the invitations table.
     555 * - Migrate requests and invitations to the new table.
     556 *
     557 * @since 2.7.0
     558 */
     559function bp_update_to_5_0() {
     560        bp_core_install_invitations();
     561        //@TODO: Migration function.
     562}
     563
    545564/**
    546565 * Updates the component field for new_members type.
    547566 *
  • new file src/bp-core/classes/class-bp-invitations-invitation.php

    diff --git src/bp-core/classes/class-bp-invitations-invitation.php src/bp-core/classes/class-bp-invitations-invitation.php
    new file mode 100644
    index 000000000..4b31771fb
    - +  
     1<?php
     2
     3/**
     4 * BuddyPress Invitations Class
     5 *
     6 * @package BuddyPress
     7 * @subpackage Invitations
     8 *
     9 * @since 5.0.0
     10 */
     11
     12// Exit if accessed directly.
     13defined( 'ABSPATH' ) || exit;
     14
     15/**
     16 * BuddyPress Invitations.
     17 *
     18 * Use this class to create, access, edit, or delete BuddyPress Invitations.
     19 *
     20 * @since 5.0.0
     21 */
     22class BP_Invitations_Invitation {
     23
     24        /**
     25         * The invitation ID.
     26         *
     27         * @since 5.0.0
     28         * @access public
     29         * @var int
     30         */
     31        public $id;
     32
     33        /**
     34         * The ID of the invited user.
     35         *
     36         * @since 5.0.0
     37         * @access public
     38         * @var int
     39         */
     40        public $user_id;
     41
     42        /**
     43         * The ID of the user who created the invitation.
     44         *
     45         * @since 5.0.0
     46         * @access public
     47         * @var int
     48         */
     49        public $inviter_id;
     50
     51        /**
     52         * The email address of the invited user.
     53         * Used when extending an invitation to someone who does not belong to the site.
     54         *
     55         * @since 5.0.0
     56         * @access public
     57         * @var string
     58         */
     59        public $invitee_email;
     60
     61        /**
     62         * The name of the related component.
     63         *
     64         * @since 5.0.0
     65         * @access public
     66         * @var string
     67         */
     68        public $component_name;
     69
     70        /**
     71         * The name of the related component action.
     72         *
     73         * @since 5.0.0
     74         * @access public
     75         * @var string
     76         */
     77        public $component_action;
     78
     79        /**
     80         * The ID associated with the invitation and component.
     81         * Example: the group ID if a group invitation
     82         *
     83         * @since 5.0.0
     84         * @access public
     85         * @var int
     86         */
     87        public $item_id;
     88
     89        /**
     90         * The secondary ID associated with the invitation and component.
     91         * Example: a taxonomy term ID if invited to a site's category-specific RSS feed
     92         *
     93         * @since 5.0.0
     94         * @access public
     95         * @var int
     96         */
     97        public $secondary_item_id = null;
     98
     99
     100        /**
     101         * Invite or request.
     102         *
     103         * @since 5.0.0
     104         * @access public
     105         * @var string
     106         */
     107        public $type;
     108
     109        /**
     110         * Extra information provided by the requester or inviter.
     111         *
     112         * @since 5.0.0
     113         * @access public
     114         * @var string
     115         */
     116        public $content;
     117
     118        /**
     119         * The date the invitation was last modified.
     120         *
     121         * @since 5.0.0
     122         * @access public
     123         * @var string
     124         */
     125        public $date_modified;
     126
     127        /**
     128         * Has the invitation been sent, or is it a draft invite?
     129         *
     130         * @since 5.0.0
     131         * @access public
     132         * @var bool
     133         */
     134        public $invite_sent;
     135
     136        /**
     137         * Has the invitation been accepted by the invitee?
     138         *
     139         * @since 5.0.0
     140         * @access public
     141         * @var bool
     142         */
     143        public $accepted;
     144
     145
     146        /** Public Methods ****************************************************/
     147
     148        /**
     149         * Constructor method.
     150         *
     151         * @since 5.0.0
     152         *
     153         * @param int $id Optional. Provide an ID to access an existing
     154         *        invitation item.
     155         */
     156        public function __construct( $id = 0 ) {
     157                if ( ! empty( $id ) ) {
     158                        $this->id = (int) $id;
     159                        $this->populate();
     160                }
     161        }
     162
     163        /**
     164         * Update or insert invitation details into the database.
     165         *
     166         * @since 5.0.0
     167         *
     168         * @global wpdb $wpdb WordPress database object.
     169         *
     170         * @return bool True on success, false on failure.
     171         */
     172        public function save() {
     173
     174                // Return value
     175                $retval = false;
     176
     177                // Default data and format
     178                $data = array(
     179                        'user_id'           => $this->user_id,
     180                        'inviter_id'        => $this->inviter_id,
     181                        'invitee_email'     => $this->invitee_email,
     182                        'component_name'    => $this->component_name,
     183                        'component_action'  => $this->component_action,
     184                        'item_id'           => $this->item_id,
     185                        'secondary_item_id' => $this->secondary_item_id,
     186                        'type'              => $this->type,
     187                        'content'           => $this->content,
     188                        'date_modified'     => $this->date_modified,
     189                        'invite_sent'       => $this->invite_sent,
     190                        'accepted'          => $this->accepted,
     191                );
     192                $data_format = array( '%d', '%d', '%s', '%s', '%s', '%d', '%d', '%s', '%s', '%s', '%d', '%d' );
     193
     194                /**
     195                 * Fires before an invitation is saved.
     196                 *
     197                 * @since 5.0.0
     198                 *
     199                 * @param BP_Invitations_Invitation object $this Characteristics of the invitation to be saved.
     200                 */
     201                do_action_ref_array( 'bp_invitation_before_save', array( &$this ) );
     202
     203                // Update
     204                if ( ! empty( $this->id ) ) {
     205                        $result = self::_update( $data, array( 'ID' => $this->id ), $data_format, array( '%d' ) );
     206                // Insert
     207                } else {
     208                        $result = self::_insert( $data, $data_format );
     209                }
     210
     211                // Set the invitation ID if successful
     212                if ( ! empty( $result ) && ! is_wp_error( $result ) ) {
     213                        global $wpdb;
     214
     215                        $this->id = $wpdb->insert_id;
     216                        $retval   = $wpdb->insert_id;
     217                }
     218
     219                /**
     220                 * Fires after an invitation is saved.
     221                 *
     222                 * @since 5.0.0
     223                 *
     224                 * @param BP_Invitations_Invitation object $this Characteristics of the invitation just saved.
     225                 */
     226                do_action_ref_array( 'bp_invitation_after_save', array( &$this ) );
     227
     228                // Return the result
     229                return $retval;
     230        }
     231
     232        /**
     233         * Fetch data for an existing invitation from the database.
     234         *
     235         * @since 5.0.0
     236         *
     237         * @global BuddyPress $bp The one true BuddyPress instance.
     238         * @global wpdb $wpdb WordPress database object.
     239         */
     240        public function populate() {
     241                global $wpdb;
     242                $invites_table_name = BP_Invitations::get_table_name();
     243
     244                // Check cache for invitation data.
     245                $invitation = wp_cache_get( $this->id, 'bp_invitations' );
     246
     247                // Cache missed, so query the DB.
     248                if ( false === $invitation ) {
     249                        $invitation = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$invites_table_name} WHERE id = %d", $this->id ) );
     250                        wp_cache_set( $this->id, $invitation,'bp_invitations' );
     251                }
     252
     253                // No invitation found so set the ID and bail.
     254                if ( empty( $invitation ) || is_wp_error( $invitation ) ) {
     255                        $this->id = 0;
     256                        return;
     257                }
     258
     259                $this->user_id           = (int) $invitation->user_id;
     260                $this->inviter_id        = (int) $invitation->inviter_id;
     261                $this->invitee_email     = $invitation->invitee_email;
     262                $this->component_name    = $invitation->component_name;
     263                $this->component_action  = $invitation->component_action;
     264                $this->item_id           = (int) $invitation->item_id;
     265                $this->secondary_item_id = (int) $invitation->secondary_item_id;
     266                $this->type              = $invitation->type;
     267                $this->content           = $invitation->content;
     268                $this->date_modified     = $invitation->date_modified;
     269                $this->invite_sent       = (int) $invitation->invite_sent;
     270                $this->accepted          = (int) $invitation->accepted;
     271
     272        }
     273
     274        /** Protected Static Methods ******************************************/
     275
     276        /**
     277         * Create an invitation entry.
     278         *
     279         * @since 5.0.0
     280         *
     281         * @param array $data {
     282         *     Array of invitation data, passed to {@link wpdb::insert()}.
     283         *         @type int $user_id ID of the invited user.
     284         *         @type int $inviter_id ID of the user who created the invitation.
     285         *         @type string $invitee_email Email address of the invited user.
     286         *         @type string $component_name Name of the related component.
     287         *         @type string $component_action Name of the related component action.
     288         *         @type int item_id ID associated with the invitation and component.
     289         *         @type int secondary_item_id secondary ID associated with the
     290         *                       invitation and component.
     291         *         @type string content Extra information provided by the requester
     292         *                       or inviter.
     293         *         @type string date_modified Date the invitation was last modified.
     294         *         @type int invite_sent Has the invitation been sent, or is it a
     295         *                       draft invite?
     296         * }
     297         * @param array $data_format See {@link wpdb::insert()}.
     298         * @return int|false The number of rows inserted, or false on error.
     299         */
     300        protected static function _insert( $data = array(), $data_format = array() ) {
     301                global $wpdb;
     302                return $wpdb->insert( BP_Invitations::get_table_name(), $data, $data_format );
     303        }
     304
     305        /**
     306         * Update invitations.
     307         *
     308         * @since 5.0.0
     309         *
     310         * @see wpdb::update() for further description of paramater formats.
     311         *
     312         * @param array $data Array of invitation data to update, passed to
     313         *        {@link wpdb::update()}. Accepts any property of a
     314         *        BP_Invitations_Invitation object.
     315         * @param array $where The WHERE params as passed to wpdb::update().
     316         *        Typically consists of array( 'ID' => $id ) to specify the ID
     317         *        of the item being updated. See {@link wpdb::update()}.
     318         * @param array $data_format See {@link wpdb::insert()}.
     319         * @param array $where_format See {@link wpdb::insert()}.
     320         * @return int|false The number of rows updated, or false on error.
     321         */
     322        protected static function _update( $data = array(), $where = array(), $data_format = array(), $where_format = array() ) {
     323                global $wpdb;
     324                return $wpdb->update( BP_Invitations::get_table_name(), $data, $where, $data_format, $where_format );
     325        }
     326
     327        /**
     328         * Delete invitations.
     329         *
     330         * @since 5.0.0
     331         *
     332         * @see wpdb::update() for further description of paramater formats.
     333         *
     334         * @param array $where Array of WHERE clauses to filter by, passed to
     335         *        {@link wpdb::delete()}. Accepts any property of a
     336         *        BP_Invitations_Invitation object.
     337         * @param array $where_format See {@link wpdb::insert()}.
     338         * @return int|false The number of rows updated, or false on error.
     339         */
     340        protected static function _delete( $where = array(), $where_format = array() ) {
     341                global $wpdb;
     342                return $wpdb->delete( BP_Invitations::get_table_name(), $where, $where_format );
     343        }
     344
     345        /**
     346         * Assemble the WHERE clause of a get() SQL statement.
     347         *
     348         * Used by BP_Invitations_Invitation::get() to create its WHERE
     349         * clause.
     350         *
     351         * @since 5.0.0
     352         *
     353         * @param array $args See {@link BP_Invitations_Invitation::get()}
     354         *        for more details.
     355         * @return string WHERE clause.
     356         */
     357        protected static function get_where_sql( $args = array() ) {
     358                global $wpdb;
     359
     360                $where_conditions = array();
     361                $where            = '';
     362
     363                // id
     364                if ( ! empty( $args['id'] ) ) {
     365                        $id_in = implode( ',', wp_parse_id_list( $args['id'] ) );
     366                        $where_conditions['id'] = "id IN ({$id_in})";
     367                }
     368
     369                // user_id
     370                if ( ! empty( $args['user_id'] ) ) {
     371                        $user_id_in = implode( ',', wp_parse_id_list( $args['user_id'] ) );
     372                        $where_conditions['user_id'] = "user_id IN ({$user_id_in})";
     373                }
     374
     375                // inviter_id. 0 can be meaningful, in the case of requests.
     376                if ( ! empty( $args['inviter_id'] ) || 0 === $args['inviter_id'] ) {
     377                        $inviter_id_in = implode( ',', wp_parse_id_list( $args['inviter_id'] ) );
     378                        $where_conditions['inviter_id'] = "inviter_id IN ({$inviter_id_in})";
     379                }
     380
     381                // invitee_email
     382                if ( ! empty( $args['invitee_email'] ) ) {
     383                        if ( ! is_array( $args['invitee_email'] ) ) {
     384                                $invitee_emails = explode( ',', $args['invitee_email'] );
     385                        } else {
     386                                $invitee_emails = $args['invitee_email'];
     387                        }
     388
     389                        $email_clean = array();
     390                        foreach ( $invitee_emails as $email ) {
     391                                $email_clean[] = $wpdb->prepare( '%s', $email );
     392                        }
     393
     394                        $invitee_email_in = implode( ',', $email_clean );
     395                        $where_conditions['invitee_email'] = "invitee_email IN ({$invitee_email_in})";
     396                }
     397
     398                // component_name
     399                if ( ! empty( $args['component_name'] ) ) {
     400                        if ( ! is_array( $args['component_name'] ) ) {
     401                                $component_names = explode( ',', $args['component_name'] );
     402                        } else {
     403                                $component_names = $args['component_name'];
     404                        }
     405
     406                        $cn_clean = array();
     407                        foreach ( $component_names as $cn ) {
     408                                $cn_clean[] = $wpdb->prepare( '%s', $cn );
     409                        }
     410
     411                        $cn_in = implode( ',', $cn_clean );
     412                        $where_conditions['component_name'] = "component_name IN ({$cn_in})";
     413                }
     414
     415                // component_action
     416                if ( ! empty( $args['component_action'] ) ) {
     417                        if ( ! is_array( $args['component_action'] ) ) {
     418                                $component_actions = explode( ',', $args['component_action'] );
     419                        } else {
     420                                $component_actions = $args['component_action'];
     421                        }
     422
     423                        $ca_clean = array();
     424                        foreach ( $component_actions as $ca ) {
     425                                $ca_clean[] = $wpdb->prepare( '%s', $ca );
     426                        }
     427
     428                        $ca_in = implode( ',', $ca_clean );
     429                        $where_conditions['component_action'] = "component_action IN ({$ca_in})";
     430                }
     431
     432                // item_id
     433                if ( ! empty( $args['item_id'] ) ) {
     434                        $item_id_in = implode( ',', wp_parse_id_list( $args['item_id'] ) );
     435                        $where_conditions['item_id'] = "item_id IN ({$item_id_in})";
     436                }
     437
     438                // secondary_item_id
     439                if ( ! empty( $args['secondary_item_id'] ) ) {
     440                        $secondary_item_id_in = implode( ',', wp_parse_id_list( $args['secondary_item_id'] ) );
     441                        $where_conditions['secondary_item_id'] = "secondary_item_id IN ({$secondary_item_id_in})";
     442                }
     443
     444                // type
     445                if ( ! empty( $args['type'] ) && 'all' !== $args['type'] ) {
     446                        if ( 'invite' == $args['type'] || 'request' == $args['type'] ) {
     447                                $type_clean = $wpdb->prepare( '%s', $args['type'] );
     448                                $where_conditions['type'] = "type = {$type_clean}";
     449                        }
     450                }
     451
     452                // invite_sent
     453                // Only create a where statement if something less than "all" has been
     454                // specifically requested.
     455                if ( ! empty( $args['invite_sent'] ) && 'all' !== $args['invite_sent'] ) {
     456                        if ( $args['invite_sent'] == 'draft' ) {
     457                                $where_conditions['invite_sent'] = "invite_sent = 0";
     458                        } else if ( $args['invite_sent'] == 'sent' ) {
     459                                $where_conditions['invite_sent'] = "invite_sent = 1";
     460                        }
     461                }
     462
     463                // accepted
     464                if ( ! empty( $args['accepted'] ) && 'all' !== $args['accepted'] ) {
     465                        if ( $args['accepted'] == 'pending' ) {
     466                                $where_conditions['accepted'] = "accepted = 0";
     467                        } else if ( $args['accepted'] == 'accepted' ) {
     468                                $where_conditions['accepted'] = "accepted = 1";
     469                        }
     470                }
     471
     472                // search_terms
     473                if ( ! empty( $args['search_terms'] ) ) {
     474                        $search_terms_like = '%' . bp_esc_like( $args['search_terms'] ) . '%';
     475                        $where_conditions['search_terms'] = $wpdb->prepare( "( component_name LIKE %s OR component_action LIKE %s )", $search_terms_like, $search_terms_like );
     476                }
     477
     478                // Custom WHERE
     479                if ( ! empty( $where_conditions ) ) {
     480                        $where = 'WHERE ' . implode( ' AND ', $where_conditions );
     481                }
     482
     483                return $where;
     484        }
     485
     486        /**
     487         * Assemble the ORDER BY clause of a get() SQL statement.
     488         *
     489         * Used by BP_Invitations_Invitation::get() to create its ORDER BY
     490         * clause.
     491         *
     492         * @since 5.0.0
     493         *
     494         * @param array $args See {@link BP_Invitations_Invitation::get()}
     495         *        for more details.
     496         * @return string ORDER BY clause.
     497         */
     498        protected static function get_order_by_sql( $args = array() ) {
     499
     500                // Setup local variable
     501                $conditions = array();
     502                $retval     = '';
     503
     504                // Order by
     505                if ( ! empty( $args['order_by'] ) ) {
     506                        $order_by               = implode( ', ', (array) $args['order_by'] );
     507                        $conditions['order_by'] = "{$order_by}";
     508                }
     509
     510                // Sort order direction
     511                if ( ! empty( $args['sort_order'] ) ) {
     512                        $sort_order               = bp_esc_sql_order( $args['sort_order'] );
     513                        $conditions['sort_order'] = "{$sort_order}";
     514                }
     515
     516                // Custom ORDER BY
     517                if ( ! empty( $conditions ) ) {
     518                        $retval = 'ORDER BY ' . implode( ' ', $conditions );
     519                }
     520
     521                return $retval;
     522        }
     523
     524        /**
     525         * Assemble the LIMIT clause of a get() SQL statement.
     526         *
     527         * Used by BP_Invitations_Invitation::get() to create its LIMIT clause.
     528         *
     529         * @since 5.0.0
     530         *
     531         * @param array $args See {@link BP_Invitations_Invitation::get()}
     532         *        for more details.
     533         * @return string LIMIT clause.
     534         */
     535        protected static function get_paged_sql( $args = array() ) {
     536                global $wpdb;
     537
     538                // Setup local variable
     539                $retval = '';
     540
     541                // Custom LIMIT
     542                if ( ! empty( $args['page'] ) && ! empty( $args['per_page'] ) ) {
     543                        $page     = absint( $args['page']     );
     544                        $per_page = absint( $args['per_page'] );
     545                        $offset   = $per_page * ( $page - 1 );
     546                        $retval   = $wpdb->prepare( "LIMIT %d, %d", $offset, $per_page );
     547                }
     548
     549                return $retval;
     550        }
     551
     552        /**
     553         * Assemble query clauses, based on arguments, to pass to $wpdb methods.
     554         *
     555         * The insert(), update(), and delete() methods of {@link wpdb} expect
     556         * arguments of the following forms:
     557         *
     558         * - associative arrays whose key/value pairs are column => value, to
     559         *   be used in WHERE, SET, or VALUES clauses
     560         * - arrays of "formats", which tell $wpdb->prepare() which type of
     561         *   value to expect when sanitizing (eg, array( '%s', '%d' ))
     562         *
     563         * This utility method can be used to assemble both kinds of params,
     564         * out of a single set of associative array arguments, such as:
     565         *
     566         *     $args = array(
     567         *         'user_id' => 4,
     568         *         'component_name' => 'groups',
     569         *     );
     570         *
     571         * This will be converted to:
     572         *
     573         *     array(
     574         *         'data' => array(
     575         *             'user_id' => 4,
     576         *             'component_name' => 'groups',
     577         *         ),
     578         *         'format' => array(
     579         *             '%d',
     580         *             '%s',
     581         *         ),
     582         *     )
     583         *
     584         * which can easily be passed as arguments to the $wpdb methods.
     585         *
     586         * @since 5.0.0
     587         *
     588         * @param $args Associative array of filter arguments.
     589         *        See {@BP_Invitations_Invitation::get()} for a breakdown.
     590         * @return array Associative array of 'data' and 'format' args.
     591         */
     592        protected static function get_query_clauses( $args = array() ) {
     593                $where_clauses = array(
     594                        'data'   => array(),
     595                        'format' => array(),
     596                );
     597
     598                // id
     599                if ( ! empty( $args['id'] ) ) {
     600                        $where_clauses['data']['id'] = absint( $args['id'] );
     601                        $where_clauses['format'][] = '%d';
     602                }
     603
     604                // user_id
     605                if ( ! empty( $args['user_id'] ) ) {
     606                        $where_clauses['data']['user_id'] = absint( $args['user_id'] );
     607                        $where_clauses['format'][] = '%d';
     608                }
     609
     610                // inviter_id
     611                if ( ! empty( $args['inviter_id'] ) ) {
     612                        $where_clauses['data']['inviter_id'] = absint( $args['inviter_id'] );
     613                        $where_clauses['format'][] = '%d';
     614                }
     615
     616                // invitee_email
     617                if ( ! empty( $args['invitee_email'] ) ) {
     618                        $where_clauses['data']['invitee_email'] = $args['invitee_email'];
     619                        $where_clauses['format'][] = '%s';
     620                }
     621
     622                // component_name
     623                if ( ! empty( $args['component_name'] ) ) {
     624                        $where_clauses['data']['component_name'] = $args['component_name'];
     625                        $where_clauses['format'][] = '%s';
     626                }
     627
     628                // component_action
     629                if ( ! empty( $args['component_action'] ) ) {
     630                        $where_clauses['data']['component_action'] = $args['component_action'];
     631                        $where_clauses['format'][] = '%s';
     632                }
     633
     634                // item_id
     635                if ( ! empty( $args['item_id'] ) ) {
     636                        $where_clauses['data']['item_id'] = absint( $args['item_id'] );
     637                        $where_clauses['format'][] = '%d';
     638                }
     639
     640                // secondary_item_id
     641                if ( ! empty( $args['secondary_item_id'] ) ) {
     642                        $where_clauses['data']['secondary_item_id'] = absint( $args['secondary_item_id'] );
     643                        $where_clauses['format'][] = '%d';
     644                }
     645
     646                // type
     647                if ( ! empty( $args['type'] ) && 'all' !== $args['type'] ) {
     648                        if ( 'invite' == $args['type'] || 'request' == $args['type'] ) {
     649                                $where_clauses['data']['type'] = $args['type'];
     650                                $where_clauses['format'][] = '%s';
     651                        }
     652                }
     653
     654                // invite_sent
     655                // Only create a where statement if something less than "all" has been
     656                // specifically requested.
     657                if ( isset( $args['invite_sent'] ) && 'all' !== $args['invite_sent'] ) {
     658                        if ( $args['invite_sent'] == 'draft' ) {
     659                                $where_clauses['data']['invite_sent'] = 0;
     660                                $where_clauses['format'][] = '%d';
     661                        } else if ( $args['invite_sent'] == 'sent' ) {
     662                                $where_clauses['data']['invite_sent'] = 1;
     663                                $where_clauses['format'][] = '%d';
     664                        }
     665                }
     666
     667                // accepted
     668                if ( ! empty( $args['accepted'] ) && 'all' !== $args['accepted'] ) {
     669                        if ( $args['accepted'] == 'pending' ) {
     670                                $where_clauses['data']['accepted'] = 0;
     671                                $where_clauses['format'][] = '%d';
     672                        } else if ( $args['accepted'] == 'accepted' ) {
     673                                $where_clauses['data']['accepted'] = 1;
     674                                $where_clauses['format'][] = '%d';
     675                        }
     676                }
     677
     678                return $where_clauses;
     679        }
     680
     681        /** Public Static Methods *********************************************/
     682
     683        /**
     684         * Get invitations, based on provided filter parameters.
     685         *
     686         * @since 5.0.0
     687         *
     688         * @param array $args {
     689         *     Associative array of arguments. All arguments but $page and
     690         *     $per_page can be treated as filter values for get_where_sql()
     691         *     and get_query_clauses(). All items are optional.
     692         *     @type int|array    $id                ID of invitation being updated.
     693         *                                           Can be an array of IDs.
     694         *     @type int|array    $user_id           ID of user being queried. Can be an
     695         *                                           Can be an array of IDs.
     696         *     @type int|array    $inviter_id        ID of user who created the
     697         *                                           invitation. Can be an array of IDs.
     698         *     @type string|array $invitee_email     Email address of invited users
     699         *                                                       being queried. Can be an array of
     700         *                                           addresses.
     701         *     @type string|array $component_name    Name of the component to filter by.
     702         *                                           Can be an array of component names.
     703         *     @type string|array $component_action  Name of the action to filter by.
     704         *                                           Can be an array of actions.
     705         *     @type int|array    $item_id           ID of associated item.
     706         *                                           Can be an array of multiple item IDs.
     707         *     @type int|array    $secondary_item_id ID of secondary associated item.
     708         *                                           Can be an array of multiple IDs.
     709         *     @type string|array $type              Type of item. An "invite" is sent
     710         *                                           from one user to another.
     711         *                                           A "request" is submitted by a
     712         *                                           user and no inviter is required.
     713         *                                           'all' returns all. Default: 'all'.
     714         *     @type string       $invite_sent       Limit to draft, sent or all
     715         *                                           'draft' limits to unsent invites,
     716         *                                           'sent' returns only sent invites,
     717         *                                           'all' returns all. Default: 'all'.
     718         *     @type bool         $accepted          Limit to accepted or
     719         *                                           not-yet-accepted invitations.
     720         *                                           'accepted' returns accepted invites,
     721         *                                           'pending' returns pending invites,
     722         *                                           'all' returns all. Default: 'pending'
     723         *     @type string       $search_terms      Term to match against component_name
     724         *                                           or component_action fields.
     725         *     @type string       $order_by          Database column to order by.
     726         *     @type string       $sort_order        Either 'ASC' or 'DESC'.
     727         *     @type string       $order_by          Field to order results by.
     728         *     @type string       $sort_order        ASC or DESC.
     729         *     @type int          $page              Number of the current page of results.
     730         *                                           Default: false (no pagination,
     731         *                                           all items).
     732         *     @type int          $per_page          Number of items to show per page.
     733         *                                           Default: false (no pagination,
     734         *                                           all items).
     735         *     @type string       $fields            Which fields to return. Specify 'item_ids' to fetch a list of Item_IDs.
     736         *                                           Specify 'ids' to fetch a list of Invitation IDs.
     737         *                                           Default: 'all' (return BP_Invitations_Invitation objects).
     738         * }
     739         *
     740         * @return array BP_Invitations_Invitation objects | IDs of found invit.
     741         */
     742        public static function get( $args = array() ) {
     743                global $wpdb;
     744                $invites_table_name = BP_Invitations::get_table_name();
     745
     746                // Parse the arguments
     747                $r  = bp_parse_args( $args, array(
     748                        'id'                => false,
     749                        'user_id'           => false,
     750                        'inviter_id'        => false,
     751                        'invitee_email'     => false,
     752                        'component_name'    => false,
     753                        'component_action'  => false,
     754                        'item_id'           => false,
     755                        'secondary_item_id' => false,
     756                        'type'              => 'all',
     757                        'invite_sent'       => 'all',
     758                        'accepted'          => 'pending',
     759                        'search_terms'      => '',
     760                        'order_by'          => false,
     761                        'sort_order'        => false,
     762                        'page'              => false,
     763                        'per_page'          => false,
     764                        'fields'            => 'all',
     765                ), 'bp_invitations_invitation_get' );
     766
     767                $sql = array(
     768                        'select'     => "SELECT",
     769                        'fields'     => '',
     770                        'from'       => "FROM {$invites_table_name} i",
     771                        'where'      => '',
     772                        'orderby'    => '',
     773                        'pagination' => '',
     774                );
     775
     776                if ( 'item_ids' === $r['fields'] ) {
     777                        $sql['fields'] = "DISTINCT i.item_id";
     778                } else if ( 'user_ids' === $r['fields'] ) {
     779                        $sql['fields'] = "DISTINCT i.user_id";
     780                } else {
     781                        $sql['fields'] = 'DISTINCT i.id';
     782                }
     783
     784                // WHERE
     785                $sql['where'] = self::get_where_sql( array(
     786                        'id'                => $r['id'],
     787                        'user_id'           => $r['user_id'],
     788                        'inviter_id'            => $r['inviter_id'],
     789                        'invitee_email'     => $r['invitee_email'],
     790                        'component_name'    => $r['component_name'],
     791                        'component_action'  => $r['component_action'],
     792                        'item_id'           => $r['item_id'],
     793                        'secondary_item_id' => $r['secondary_item_id'],
     794                        'type'              => $r['type'],
     795                        'invite_sent'       => $r['invite_sent'],
     796                        'accepted'          => $r['accepted'],
     797                        'search_terms'      => $r['search_terms'],
     798                ) );
     799
     800                // ORDER BY
     801                $sql['orderby'] = self::get_order_by_sql( array(
     802                        'order_by'   => $r['order_by'],
     803                        'sort_order' => $r['sort_order']
     804                ) );
     805
     806                // LIMIT %d, %d
     807                $sql['pagination'] = self::get_paged_sql( array(
     808                        'page'     => $r['page'],
     809                        'per_page' => $r['per_page'],
     810                ) );
     811
     812                $paged_invites_sql = "{$sql['select']} {$sql['fields']} {$sql['from']} {$sql['where']} {$sql['orderby']} {$sql['pagination']}";
     813
     814                /**
     815                 * Filters the pagination SQL statement.
     816                 *
     817                 * @since 5.0.0
     818                 *
     819                 * @param string $value Concatenated SQL statement.
     820                 * @param array  $sql   Array of SQL parts before concatenation.
     821                 * @param array  $r     Array of parsed arguments for the get method.
     822                 */
     823                $paged_invites_sql = apply_filters( 'bp_invitations_get_paged_invitations_sql', $paged_invites_sql, $sql, $r );
     824
     825                $cached = bp_core_get_incremented_cache( $paged_invites_sql, 'bp_invitations' );
     826                if ( false === $cached ) {
     827                        $paged_invite_ids = $wpdb->get_col( $paged_invites_sql );
     828                        bp_core_set_incremented_cache( $paged_invites_sql, 'bp_invitations', $paged_invite_ids );
     829                } else {
     830                        $paged_invite_ids = $cached;
     831                }
     832
     833                // Special return format cases.
     834                if ( 'ids' === $r['fields'] || 'item_ids' === $r['fields'] || 'user_ids' === $r['fields'] ) {
     835                        // We only want the field that was found.
     836                        return array_map( 'intval', $paged_invite_ids );
     837                }
     838
     839                $uncached_ids = bp_get_non_cached_ids( $paged_invite_ids, 'bp_invitations' );
     840                if ( $uncached_ids ) {
     841                        $ids_sql = implode( ',', array_map( 'intval', $uncached_ids ) );
     842                        $data_objects = $wpdb->get_results( "SELECT i.* FROM {$invites_table_name} i WHERE i.id IN ({$ids_sql})" );
     843                        foreach ( $data_objects as $data_object ) {
     844                                wp_cache_set( $data_object->id, $data_object, 'bp_invitations' );
     845                        }
     846                }
     847
     848                $paged_invites = array();
     849                foreach ( $paged_invite_ids as $paged_invite_id ) {
     850                        $paged_invites[] = new BP_Invitations_Invitation( $paged_invite_id );
     851                }
     852
     853                return $paged_invites;
     854        }
     855
     856        /**
     857         * Get a count of total invitations matching a set of arguments.
     858         *
     859         * @since 5.0.0
     860         *
     861         * @see BP_Invitations_Invitation::get() for a description of
     862         *      arguments.
     863         *
     864         * @param array $args See {@link BP_Invitations_Invitation::get()}.
     865         * @return int Count of located items.
     866         */
     867        public static function get_total_count( $args ) {
     868                global $wpdb;
     869                $invites_table_name = BP_Invitations::get_table_name();
     870
     871                // Build the query
     872                $select_sql = "SELECT COUNT(*)";
     873                $from_sql   = "FROM {$invites_table_name}";
     874                $where_sql  = self::get_where_sql( $args );
     875                $sql        = "{$select_sql} {$from_sql} {$where_sql}";
     876
     877                // Return the queried results
     878                return $wpdb->get_var( $sql );
     879        }
     880
     881        /**
     882         * Update invitations.
     883         *
     884         * @since 5.0.0
     885         *
     886         * @see BP_Invitations_Invitation::get() for a description of
     887         *      accepted update/where arguments.
     888         *
     889         * @param array $update_args Associative array of fields to update,
     890         *        and the values to update them to. Of the format
     891         *            array( 'user_id' => 4, 'component_name' => 'groups', )
     892         * @param array $where_args Associative array of columns/values, to
     893         *        determine which rows should be updated. Of the format
     894         *            array( 'item_id' => 7, 'component_action' => 'members', )
     895         * @return int|bool Number of rows updated on success, false on failure.
     896         */
     897        public static function update( $update_args = array(), $where_args = array() ) {
     898                $update = self::get_query_clauses( $update_args );
     899                $where  = self::get_query_clauses( $where_args  );
     900
     901                /**
     902                 * Fires before an invitation is updated.
     903                 *
     904                 * @since 5.0.0
     905                 *
     906                 * @param array $where_args  Array of fields to update.
     907                 * @param array $update_args Array of new values.
     908                 */
     909                do_action( 'bp_invitation_before_update', $where_args, $update_args );
     910
     911                $retval = self::_update( $update['data'], $where['data'], $update['format'], $where['format'] );
     912
     913                return $retval;
     914        }
     915
     916        /**
     917         * Delete invitations.
     918         *
     919         * @since 5.0.0
     920         *
     921         * @see BP_Invitations_Invitation::get() for a description of
     922         *      accepted where arguments.
     923         *
     924         * @param array $args Associative array of columns/values, to determine
     925         *        which rows should be deleted.  Of the format
     926         *            array( 'item_id' => 7, 'component_action' => 'members', )
     927         * @return int|bool Number of rows deleted on success, false on failure.
     928         */
     929        public static function delete( $args = array() ) {
     930                $where = self::get_query_clauses( $args );
     931
     932                /**
     933                 * Fires before an invitation is deleted.
     934                 *
     935                 * @since 5.0.0
     936                 *
     937                 * @param array $args Characteristics of the invitations to be deleted.
     938                 */
     939                do_action( 'bp_invitation_before_delete', $args );
     940
     941                $retval = self::_delete( $where['data'], $where['format'] );
     942
     943                /**
     944                 * Fires after an invitation is deleted.
     945                 *
     946                 * @since 5.0.0
     947                 *
     948                 * @param array $args Characteristics of the invitations just deleted.
     949                 */
     950                do_action( 'bp_invitation_after_delete', $args );
     951
     952                return $retval;
     953        }
     954
     955        /** Convenience methods ***********************************************/
     956
     957        /**
     958         * Delete a single invitation by ID.
     959         *
     960         * @since 5.0.0
     961         *
     962         * @see BP_Invitations_Invitation::delete() for explanation of
     963         *      return value.
     964         *
     965         * @param int $id ID of the invitation item to be deleted.
     966         * @return bool True on success, false on failure.
     967         */
     968        public static function delete_by_id( $id ) {
     969                return self::delete( array(
     970                        'id' => $id,
     971                ) );
     972        }
     973
     974        /** Sent status ***********************************************************/
     975
     976        /**
     977         * Mark specific invitations as sent by invitation ID.
     978         *
     979         * @since 5.0.0
     980         *
     981         * @param int $id The ID of the invitation to mark as sent.
     982         */
     983        public static function mark_sent( $id = 0 ) {
     984
     985                if ( ! $id ) {
     986                        return false;
     987                }
     988
     989                // Values to be updated
     990                $update_args = array(
     991                        'invite_sent' => 'sent',
     992                );
     993
     994                // WHERE clauses
     995                $where_args = array(
     996                        'id' => $id,
     997                );
     998
     999                return self::update( $update_args, $where_args );
     1000        }
     1001
     1002        /**
     1003         * Mark invitations as sent that are found by user_id, inviter_id, item id, and optional
     1004         * secondary item id, and component name and action.
     1005         *
     1006         * @since 5.0.0
     1007         *
     1008         * @param array $args See BP_Invitations_Invitation::update().
     1009         */
     1010        public static function mark_sent_by_data( $args ) {
     1011
     1012                // Values to be updated
     1013                $update_args = array(
     1014                        'invite_sent' => 'sent',
     1015                );
     1016
     1017                return self::update( $update_args, $args );
     1018        }
     1019
     1020        /** Accepted status ***********************************************************/
     1021
     1022        /**
     1023         * Mark specific invitations as accepted by invitation ID.
     1024         *
     1025         * @since 5.0.0
     1026         *
     1027         * @param int $id The ID of the invitation to mark as sent.
     1028         */
     1029        public static function mark_accepted( $id = 0 ) {
     1030
     1031                if ( ! $id ) {
     1032                        return false;
     1033                }
     1034
     1035                // Values to be updated
     1036                $update_args = array(
     1037                        'accepted' => 'accepted',
     1038                );
     1039
     1040                // WHERE clauses
     1041                $where_args = array(
     1042                        'id' => $id,
     1043                );
     1044
     1045                return self::update( $update_args, $where_args );
     1046        }
     1047
     1048        /**
     1049         * Mark invitations as accepted that are found by user_id, inviter_id,
     1050         * item id, and optional secondary item id, and component name and action.
     1051         *
     1052         * @since 5.0.0
     1053         *
     1054         * @param array $args See BP_Invitations_Invitation::update().
     1055         */
     1056        public static function mark_accepted_by_data( $args ) {
     1057
     1058                // Values to be updated
     1059                $update_args = array(
     1060                        'accepted' => 'accepted',
     1061                );
     1062
     1063                return self::update( $update_args, $args );
     1064        }
     1065
     1066}
  • new file src/bp-core/classes/class-bp-invitations.php

    diff --git src/bp-core/classes/class-bp-invitations.php src/bp-core/classes/class-bp-invitations.php
    new file mode 100644
    index 000000000..6abeb33c7
    - +  
     1<?php
     2/**
     3 * Core invitations class.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 * @since 5.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * BP Invitations class.
     15 *
     16 * Extend it to manage your component's invitations.
     17 *
     18 * @since 5.0.0
     19 */
     20class BP_Invitations {
     21
     22        /**
     23         * The name of the related component.
     24         *
     25         * @since 5.0.0
     26         * @access public
     27         * @var string
     28         */
     29        protected $component_name;
     30
     31        /**
     32         * Construct parameters.
     33         *
     34         * @since 5.0.0
     35         *
     36         * @param array|string $args {
     37
     38         * }
     39         */
     40        public function __construct( $args = array() ) {
     41                // Component name is required.
     42                if ( empty( $args['component_name'] ) ) {
     43                        return false;
     44                }
     45
     46                $this->component_name = sanitize_key( $args['component_name'] );
     47        }
     48
     49        /**
     50         * Get the invitations table name.
     51         *
     52         * @since 5.0.0
     53         * @access public
     54         * @return string
     55         */
     56        public static function get_table_name() {
     57                return buddypress()->table_prefix . 'bp_invitations';
     58        }
     59
     60        /** Create ********************************************************************/
     61
     62        /**
     63         * Add an invitation to a specific user, from a specific user, related to a
     64         * specific component.
     65         *
     66         * @since 5.0.0
     67         *
     68         * @param array $args {
     69         *     Array of arguments describing the invitation. All are optional.
     70         *         @type int    $user_id ID of the invited user.
     71         *         @type int    $inviter_id ID of the user who created the invitation.
     72         *         @type string $invitee_email Email address of the invited user.
     73         *         @type string $component_name Name of the related component.
     74         *         @type string $component_action Name of the related component action.
     75         *         @type int    $item_id ID associated with the invitation and component.
     76         *         @type int    $secondary_item_id secondary ID associated with the
     77         *                              invitation and component.
     78         *         @type string $type @TODO.
     79         *         @type string $content Extra information provided by the requester
     80         *                              or inviter.
     81         *         @type string $date_modified Date the invitation was last modified.
     82         *         @type int    $send_invite Should the invitation also be sent, or is it a
     83         *                       draft invite?
     84         * }
     85         * @return int|bool ID of the newly created invitation on success, false
     86         *         on failure.
     87         */
     88        public function add_invitation( $args = array() ) {
     89
     90                $r = bp_parse_args( $args, array(
     91                        'user_id'           => 0,
     92                        'invitee_email'         => '',
     93                        'inviter_id'            => 0,
     94                        'component_action'  => '',
     95                        'item_id'           => 0,
     96                        'secondary_item_id' => 0,
     97                        'type'                          => 'invite',
     98                        'content'                       => '',
     99                        'date_modified'     => bp_core_current_time(),
     100                        'send_invite'       => 0,
     101                        'accepted'          => 0
     102                ), 'add_invitation' );
     103
     104                // Invitations must have an invitee and inviter.
     105                if ( ! ( ( $r['user_id'] || $r['invitee_email'] ) && $r['inviter_id'] ) ) {
     106                        return false;
     107                }
     108
     109                /**
     110                 * Is this user allowed to extend invitations from this component/item?
     111                 *
     112                 * @since 5.0.0
     113                 *
     114                 * @param array $r Describes the invitation to be added.
     115                 */
     116                if ( ! $this->allow_invitation( $r ) ) {
     117                        return false;
     118                }
     119
     120                // Avoid creating duplicate invitations.
     121                $invite_id = $this->invitation_exists( array(
     122                        'user_id'           => $r['user_id'],
     123                        'invitee_email'     => $r['invitee_email'],
     124                        'inviter_id'        => $r['inviter_id'],
     125                        'component_action'  => $r['component_action'],
     126                        'item_id'           => $r['item_id'],
     127                        'secondary_item_id' => $r['secondary_item_id'],
     128                ) );
     129
     130                if ( ! $invite_id ) {
     131                        // Set up the new invitation as a draft.
     132                        $invitation                    = new BP_Invitations_Invitation;
     133                        $invitation->user_id           = $r['user_id'];
     134                        $invitation->inviter_id        = $r['inviter_id'];
     135                        $invitation->invitee_email     = $r['invitee_email'];
     136                        $invitation->component_name    = $this->component_name;
     137                        $invitation->component_action  = $r['component_action'];
     138                        $invitation->item_id           = $r['item_id'];
     139                        $invitation->secondary_item_id = $r['secondary_item_id'];
     140                        $invitation->type              = $r['type'];
     141                        $invitation->content           = $r['content'];
     142                        $invitation->date_modified     = $r['date_modified'];
     143                        $invitation->invite_sent       = 0;
     144                        $invitation->accepted          = 0;
     145
     146                        $invite_id = $invitation->save();
     147                }
     148
     149                // "Send" the invite if necessary.
     150                if ( $invite_id && $r['send_invite'] ) {
     151                                $sent = $this->send_invitation_by_id( $invite_id );
     152                        if ( ! $sent ) {
     153                                return false;
     154                        }
     155                }
     156
     157                return $invite_id;
     158        }
     159
     160        /**
     161         * Send an invitation notification.
     162         *
     163         * @since 5.0.0
     164         * @access public
     165         *
     166         * @param int $invitation_id ID of invitation to send.
     167         *
     168         * @return int|bool The number of rows updated, or false on error.
     169         */
     170        public function send_invitation_by_id( $invitation_id = 0 ) {
     171                $updated = false;
     172
     173                $invitation = new BP_Invitations_Invitation( $invitation_id );
     174
     175                if ( ! $invitation->id ) {
     176                        return false;
     177                }
     178
     179                /**
     180                 * Fires before an invitation is sent.
     181                 *
     182                 * @since 5.0.0
     183                 *
     184                 * @param BP_Invitations_Invitation object $invitation Invitation about to be sent.
     185                 */
     186                do_action( 'bp_invitations_send_invitation_by_id_before_send', $invitation );
     187
     188                /*
     189                 * Before sending an invitation, check for outstanding requests to the same item.
     190                 * A sent invitation + a request = acceptance.
     191                 */
     192                $request_args = array(
     193                        'user_id'           => $invitation->user_id,
     194                        'invitee_email'     => $invitation->invitee_email,
     195                        'component_action'  => $invitation->component_action,
     196                        'item_id'           => $invitation->item_id,
     197                        'secondary_item_id' => $invitation->secondary_item_id,
     198                );
     199                $request = $this->request_exists( $request_args );
     200
     201                if ( ! empty( $request ) ) {
     202                        // Accept the request.
     203                        return $this->accept_request( $request_args );
     204                }
     205
     206                // Perform the send action.
     207                $this->run_send_action( $invitation );
     208
     209                $updated = BP_Invitations_Invitation::mark_sent( $invitation->id );
     210
     211                return $updated;
     212        }
     213
     214        /**
     215         * Add a request to an item for a specific user, related to a
     216         * specific component.
     217         *
     218         * @since 5.0.0
     219         *
     220         * @param array $args {
     221         *     Array of arguments describing the invitation. All are optional.
     222         *         @type int    $user_id ID of the invited user.
     223         *         @type int    $inviter_id ID of the user who created the invitation.
     224         *         @type string $component_name Name of the related component.
     225         *         @type string $component_action Name of the related component action.
     226         *         @type int    $item_id ID associated with the invitation and component.
     227         *         @type int    $secondary_item_id secondary ID associated with the
     228         *                              invitation and component.
     229         *         @type string $type @TODO.
     230         *         @type string $content Extra information provided by the requester
     231         *                              or inviter.
     232         *         @type string $date_modified Date the invitation was last modified.
     233         *         @type int    $invite_sent Has the invitation been sent, or is it a
     234         *                       draft invite?
     235         * }
     236         * @return int|bool ID of the newly created invitation on success, false
     237         *         on failure.
     238         */
     239        public function add_request( $args = array() ) {
     240
     241                $r = bp_parse_args( $args, array(
     242                        'user_id'           => 0,
     243                        'inviter_id'        => 0,
     244                        'invitee_email'     => '',
     245                        'component_action'  => '',
     246                        'item_id'           => 0,
     247                        'secondary_item_id' => 0,
     248                        'type'              => 'request',
     249                        'content'           => '',
     250                        'date_modified'     => bp_core_current_time(),
     251                        'invite_sent'       => 0,
     252                        'accepted'          => 0
     253                ), 'add_request' );
     254
     255                // If there is no invitee, bail.
     256                if ( ! ( $r['user_id'] || $r['invitee_email'] ) ) {
     257                                return false;
     258                }
     259
     260                /**
     261                 * Is this user allowed to make a request to this component/item?
     262                 *
     263                 * @since 5.0.0
     264                 *
     265                 * @param array $r Describes the invitation to be added.
     266                 */
     267                if ( ! $this->allow_request( $r ) ) {
     268                        return false;
     269                }
     270
     271                /*
     272                 * Avoid creating duplicate requests.
     273                 */
     274                $base_args = array(
     275                        'user_id'           => $r['user_id'],
     276                        'invitee_email'     => $r['invitee_email'],
     277                        'component_action'  => $r['component_action'],
     278                        'item_id'           => $r['item_id'],
     279                        'secondary_item_id' => $r['secondary_item_id'],
     280                );
     281                if ( $this->request_exists( $base_args ) ) {
     282                        return false;
     283                }
     284
     285                /*
     286                 * Check for outstanding invitations to the same item.
     287                 * A request + a sent invite = acceptance.
     288                 */
     289                $invite_args = array_merge( $base_args, array( 'invite_sent' => 'sent' ) );
     290                $invite = $this->invitation_exists( $invite_args );
     291
     292                if ( $invite ) {
     293                        // Accept the invite.
     294                        return $this->accept_invitation( $base_args );
     295                } else {
     296                        // Set up the new request.
     297                        $request                    = new BP_Invitations_Invitation;
     298                        $request->user_id           = $r['user_id'];
     299                        $request->inviter_id        = $r['inviter_id'];
     300                        $request->invitee_email     = $r['invitee_email'];
     301                        $request->component_name    = $this->component_name;
     302                        $request->component_action  = $r['component_action'];
     303                        $request->item_id           = $r['item_id'];
     304                        $request->secondary_item_id = $r['secondary_item_id'];
     305                        $request->type              = $r['type'];
     306                        $request->content           = $r['content'];
     307                        $request->date_modified     = $r['date_modified'];
     308                        $request->invite_sent       = $r['invite_sent'];
     309                        $request->accepted          = $r['accepted'];
     310
     311                        // Save the new invitation.
     312                        return $request->save();
     313                }
     314        }
     315
     316        /**
     317         * Send a request notification.
     318         *
     319         * @since 5.0.0
     320         * @access public
     321         *
     322         * @param int $request_id ID of request to send.
     323         *
     324         * @return int|bool The number of rows updated, or false on error.
     325         */
     326        public function send_request_notification_by_id( $request_id = 0 ) {
     327                $updated = false;
     328
     329                $request = new BP_Invitations_Invitation( $request_id );
     330
     331                if ( ! $request->id ) {
     332                        return false;
     333                }
     334
     335                // Different uses may need different actions on sending. Plugins can hook in here to perform their own tasks.
     336                do_action( 'bp_invitations_send_request_notification_by_id_before_send', $request_id, $request );
     337
     338                /*
     339                 * Before sending notifications, check for outstanding invitations to the same item.
     340                 * A sent invitation + a request = acceptance.
     341                 */
     342                $args = array(
     343                        'user_id'           => $request->user_id,
     344                        'invitee_email'     => $request->invitee_email,
     345                        'component_action'  => $request->component_action,
     346                        'item_id'           => $request->item_id,
     347                        'secondary_item_id' => $request->secondary_item_id,
     348                        'invite_sent'       => 'sent'
     349                );
     350                $invites = $this->invitation_exists( $args );
     351
     352                if ( ! empty( $invites ) ) {
     353                        // Accept the request.
     354                        return $this->accept_invitation( $args );
     355                }
     356
     357                // Perform the send action.
     358                $this->run_send_action( $request );
     359
     360                $updated = BP_Invitations_Invitation::mark_sent( $request->id );
     361
     362                return $updated;
     363        }
     364
     365        /** Retrieve ******************************************************************/
     366
     367        /**
     368         * Get a specific invitation by its ID.
     369         *
     370         * @since 5.0.0
     371         *
     372         * @param int $id ID of the invitation.
     373         * @return BP_Invitations_Invitation object
     374         */
     375        public function get_by_id( $id = 0 ) {
     376                return new BP_Invitations_Invitation( $id );
     377        }
     378
     379        /**
     380         * Get invitations, based on provided filter parameters.
     381         *
     382         * @since 5.0.0
     383         *
     384         * @see BP_Invitations_Invitation::get() for a description of accepted parameters.
     385         *
     386         * @return array Located invitations.
     387         */
     388        public function get_invitations( $args = array() ) {
     389                // Default to returning invitations, not requests.
     390                if ( empty( $args['type'] ) ) {
     391                        $args['type'] = 'invite';
     392                }
     393                // Use this class's component_name property value.
     394                $args['component_name'] = $this->component_name;
     395
     396                return BP_Invitations_Invitation::get( $args );
     397        }
     398
     399        /**
     400         * Get requests, based on provided filter parameters.
     401         *
     402         * @since 5.0.0
     403         *
     404         * @see BP_Invitations_Invitation::get() for a description of accepted parameters.
     405         *
     406         * @return array Located invitations.
     407         */
     408        public function get_requests( $args = array() ) {
     409                // Set request-specific parameters.
     410                $args['type']        = 'request';
     411                $args['inviter_id']  = false;
     412                $args['invite_sent'] = 'all';
     413
     414                // Use this class's component_name property value.
     415                $args['component_name'] = $this->component_name;
     416
     417                return BP_Invitations_Invitation::get( $args );
     418        }
     419
     420        /**
     421         * Check whether an invitation exists matching the passed arguments.
     422         *
     423         * @since 5.0.0
     424         *
     425         * @see BP_Invitations_Invitation::get() for a description of accepted parameters.
     426         *
     427         * @return bool|int ID of first found invitation or false if none found.
     428         */
     429        public function invitation_exists( $args = array() ) {
     430                $is_invited = false;
     431
     432                $args['fields'] = 'ids';
     433                $invites = $this->get_invitations( $args );
     434                if ( $invites ) {
     435                        $is_invited = current( $invites );
     436                }
     437                return $is_invited;
     438        }
     439
     440        /**
     441         * Check whether a request exists matching the passed arguments.
     442         *
     443         * @since 5.0.0
     444         *
     445         * @see BP_Invitations_Invitation::get() for a description of accepted parameters.
     446         *
     447         * @return bool|int ID of existing request or false if none found.
     448         */
     449        public function request_exists( $args = array() ) {
     450                $has_request = false;
     451
     452                $args['fields'] = 'ids';
     453                $requests = $this->get_requests( $args );
     454                if ( $requests ) {
     455                        $has_request = current( $requests );
     456                }
     457                return $has_request;
     458        }
     459
     460        /** Update ********************************************************************/
     461
     462        /**
     463         * Accept invitation, based on provided filter parameters.
     464         *
     465         * @since 5.0.0
     466         *
     467         * @see BP_Invitations_Invitation::get() for a description of
     468         *      accepted update/where arguments.
     469         *
     470         * @param array $update_args Associative array of fields to update,
     471         *              and the values to update them to. Of the format
     472         *              array( 'user_id' => 4, 'component_name' => 'groups', )
     473         *
     474         * @return int|bool Number of rows updated on success, false on failure.
     475         */
     476         public function accept_invitation( $args = array() ) {
     477
     478                /*
     479                 * Some basic info is required to accept an invitation,
     480                 * because we'll need to mark all similar invitations and requests.
     481                 * The following, except the optional 'secondary_item_id', are required.
     482                 */
     483                $r = bp_parse_args( $args, array(
     484                        'user_id'           => 0,
     485                        'invitee_email'     => '',
     486                        'component_action'  => '',
     487                        'item_id'           => null,
     488                        'secondary_item_id' => null,
     489                        'invite_sent'       => 'sent',
     490                ), 'accept_invitation' );
     491                $r['component_name'] = $this->component_name;
     492
     493                if ( ! ( ( $r['user_id'] || $r['invitee_email'] ) && $r['component_name'] && $r['item_id'] ) ) {
     494                        return false;
     495                }
     496
     497                $success = $this->run_acceptance_action( 'invite', $r );
     498                if ( $success ) {
     499                        // Mark invitations & requests to this item for this user.
     500                        $this->mark_accepted( $r );
     501
     502                        // Allow plugins an opportunity to act on the change.
     503                        do_action( 'bp_invitations_accepted_invite', $r );
     504                }
     505                return $success;
     506        }
     507
     508        /**
     509         * Accept invitation, based on provided filter parameters.
     510         *
     511         * @since 5.0.0
     512         *
     513         * @see BP_Invitations_Invitation::get() for a description of
     514         *      accepted update/where arguments.
     515         *
     516         * @param array $update_args Associative array of fields to update,
     517         *              and the values to update them to. Of the format
     518         *              array( 'user_id' => 4, 'component_name' => 'groups', )
     519         *
     520         * @return bool Number of rows updated on success, false on failure.
     521         */
     522         public function accept_request( $args = array() ) {
     523                /*
     524                 * Some basic info is required to accept an invitation,
     525                 * because we'll need to accept all similar invitations and requests.
     526                 * The following, except the optional 'secondary_item_id', are required.
     527                 */
     528                $r = bp_parse_args( $args, array(
     529                        'user_id'           => 0,
     530                        'component_action'  => '',
     531                        'item_id'           => null,
     532                        'secondary_item_id' => null,
     533                ), 'accept_request' );
     534                $r['component_name'] = $this->component_name;
     535
     536                if ( ! ( $r['user_id'] && $r['component_name'] && $r['item_id'] ) ) {
     537                        return false;
     538                }
     539
     540                $success = $this->run_acceptance_action( 'request', $r );
     541                if ( $success ) {
     542                        // Update/Delete all related invitations & requests to this item for this user.
     543                        $this->mark_accepted( $r );
     544
     545                        // Allow plugins an opportunity to act on the change.
     546                        do_action( 'bp_invitations_accepted_request', $r );
     547                }
     548                return $success;
     549        }
     550
     551        /**
     552         * Update invitation, based on provided filter parameters.
     553         *
     554         * @since 5.0.0
     555         *
     556         * @see BP_Invitations_Invitation::get() for a description of
     557         *      accepted update/where arguments.
     558         *
     559         * @param array $update_args Associative array of fields to update,
     560         *              and the values to update them to. Of the format
     561         *              array( 'user_id' => 4, 'component_name' => 'groups', )
     562         * @param array $where_args Associative array of columns/values, to
     563         *              determine which invitations should be updated. Formatted as
     564         *              array( 'item_id' => 7, 'component_action' => 'members', )
     565         * @return int|bool Number of rows updated on success, false on failure.
     566         */
     567        public function update_invitation( $update_args = array(), $where_args = array() ) {
     568                $update_args['component_name'] = $this->component_name;
     569                return BP_Invitations_Invitation::update( $update_args, $where_args );
     570        }
     571
     572
     573        /**
     574         * This is where custom actions are added (in child classes)
     575         * to run when an invitation or request needs to be "sent."
     576         *
     577         * @since 5.0.0
     578         *
     579         * @param BP_Invitations_Invitation $invitation The invitation to send.
     580         * @return bool True on success, false on failure.
     581         */
     582        public function run_send_action( BP_Invitations_Invitation $invitation ) {
     583                return true;
     584        }
     585
     586        /**
     587         * Mark invitations as sent that are found by user_id, inviter_id,
     588         * invitee_email, component name and action, optional item id,
     589         * optional secondary item id.
     590         *
     591         * @since 5.0.0
     592         *
     593         * @param array $args {
     594         *     Associative array of arguments. All arguments but $page and
     595         *     $per_page can be treated as filter values for get_where_sql()
     596         *     and get_query_clauses(). All items are optional.
     597         *     @type int|array    $user_id ID of user being queried. Can be an
     598         *                        array of user IDs.
     599         *     @type int|array    $inviter_id ID of user who created the
     600         *                        invitation. Can be an array of user IDs.
     601         *                        Special cases
     602         *     @type string|array $invitee_email Email address of invited users
     603         *                                    being queried. Can be an array of addresses.
     604         *     @type string|array $component_name Name of the component to
     605         *                        filter by. Can be an array of component names.
     606         *     @type string|array $component_action Name of the action to
     607         *                        filter by. Can be an array of actions.
     608         *     @type int|array    $item_id ID of associated item. Can be an array
     609         *                        of multiple item IDs.
     610         *     @type int|array    $secondary_item_id ID of secondary associated
     611         *                        item. Can be an array of multiple IDs.
     612         * }
     613         */
     614        public function mark_sent( $args ) {
     615                $args['component_name'] = $this->component_name;
     616                return BP_Invitations_Invitation::mark_sent_by_data( $args );
     617        }
     618
     619        /**
     620         * This is where custom actions are added (in child classes)
     621         * to run when an invitation or request is accepted.
     622         *
     623         * @since 5.0.0
     624         *
     625         * @param int $id The ID of the invitation to mark as sent.
     626         * @return bool True on success, false on failure.
     627         */
     628        public function run_acceptance_action( $type = 'invite', $r  ) {
     629                return true;
     630        }
     631
     632        /**
     633         * Mark invitation as accepted by invitation ID.
     634         *
     635         * @since 5.0.0
     636         *
     637         * @param int $id The ID of the invitation to mark as sent.
     638         * @return bool True on success, false on failure.
     639         */
     640        public function mark_accepted_by_id( $id ) {
     641                return BP_Invitations_Invitation::mark_accepted( $id );
     642        }
     643
     644        /**
     645         * Mark invitations as sent that are found by user_id, inviter_id,
     646         * invitee_email, component name and action, optional item id,
     647         * optional secondary item id.
     648         *
     649         * @since 5.0.0
     650         *
     651         * @see BP_Invitations_Invitation::mark_accepted_by_data()
     652         *      for a description of arguments.
     653         */
     654        public function mark_accepted( $args ) {
     655                $args['component_name'] = $this->component_name;
     656                return BP_Invitations_Invitation::mark_accepted_by_data( $args );
     657        }
     658
     659        /** Delete ********************************************************************/
     660
     661        /**
     662         * Delete an invitation or invitations by query data.
     663         *
     664         * @since 5.0.0
     665         *
     666         * @see BP_Invitations_Invitation::delete for a description of arguments.
     667         * @return int|false Number of rows deleted on success, false on failure.
     668         */
     669        public function delete( $args ) {
     670                if ( empty( $args['type'] ) ) {
     671                        $args['type'] = 'invite';
     672                }
     673                $args['component_name'] = $this->component_name;
     674                return BP_Invitations_Invitation::delete( $args );
     675        }
     676
     677        /**
     678         * Delete a request or requests by query data.
     679         *
     680         * @since 5.0.0
     681         *
     682         * @see BP_Invitations_Invitation::delete for a description of arguments.
     683         *
     684         * @return int|false Number of rows deleted on success, false on failure.
     685         */
     686        public function delete_requests( $args ) {
     687                $args['type'] = 'request';
     688                return $this->delete( $args );
     689        }
     690
     691        /**
     692         * Delete all invitations by component.
     693         *
     694         * Used when clearing out invitations for an entire component. Possibly used
     695         * when deactivating a component that created invitations.
     696         *
     697         * @since 5.0.0
     698         *
     699         * @param string $component_action Optional. Name of the associated action.
     700         * @return int|false Number of rows deleted on success, false on failure.
     701         */
     702        public function delete_all( $component_action = false ) {
     703                return BP_Invitations_Invitation::delete( array(
     704                        'component_name'    => $this->component_name,
     705                        'component_action'  => $component_action,
     706                ) );
     707        }
     708
     709        /**
     710         * This is where custom actions are added (in child classes)
     711         * to determine whether an invitation should be allowed.
     712         *
     713         * @since 5.0.0
     714         *
     715         * @param array $args The parameters describing the invitation.
     716         * @return bool True if allowed, false to end process.
     717         */
     718        public function allow_invitation( $args ) {
     719                return true;
     720        }
     721
     722        /**
     723         * This is where custom actions are added (in child classes)
     724         * to determine whether a request should be allowed.
     725         *
     726         * @since 5.0.0
     727         *
     728         * @param array $args The parameters describing the request.
     729         * @return bool True if allowed, false to end process.
     730         */
     731        public function allow_request( $args ) {
     732                return true;
     733        }
     734
     735}
  • src/bp-groups/actions/leave-group.php

    diff --git src/bp-groups/actions/leave-group.php src/bp-groups/actions/leave-group.php
    index 860e9fc1d..ed87abccf 100644
    function groups_action_leave_group() { 
    5858        /** This filter is documented in bp-groups/bp-groups-actions.php */
    5959        bp_core_load_template( apply_filters( 'groups_template_group_home', 'groups/single/home' ) );
    6060}
    61 add_action( 'bp_actions', 'groups_action_leave_group' );
    62  No newline at end of file
     61add_action( 'bp_actions', 'groups_action_leave_group' );
     62
     63/**
     64 * Clean up requests/invites when a member leaves a group.
     65 *
     66 * @since 5.0.0
     67 */
     68function groups_action_clean_up_invites_requests( $user_id, $group_id ) {
     69        $invites_class = new BP_Groups_Invitations();
     70        // Remove invitations/requests where the deleted user is the receiver.
     71        $invites_class->delete( array(
     72                'user_id' => $user_id,
     73                'item_id' => $group_id,
     74                'type'    => 'all'
     75        ) );
     76        // Remove invitations where the deleted user is the sender.
     77        $invites_class->delete( array(
     78                'inviter_id' => $user_id,
     79                'item_id'    => $group_id,
     80        ) );
     81}
     82add_action( 'bp_groups_member_after_delete', 'groups_action_clean_up_invites_requests', 10, 2 );
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index 43240122a..7daa03211 100644
    function bp_get_user_groups( $user_id, $args = array() ) { 
    949949
    950950        $user_id = intval( $user_id );
    951951
     952        // @TODO-6210: This is tied to the groups membership table. How to include invites/requests from a separate table?
    952953        $membership_ids = wp_cache_get( $user_id, 'bp_groups_memberships_for_user' );
    953954        if ( false === $membership_ids ) {
    954955                $membership_ids = BP_Groups_Member::get_membership_ids_for_user( $user_id );
    function groups_is_user_banned( $user_id, $group_id ) { 
    12091210 * Check whether a user has an outstanding invitation to a group.
    12101211 *
    12111212 * @since 2.6.0
     1213 * @since 5.0.0 Added $type parameter.
    12121214 *
    1213  * @param int $user_id ID of the user.
    1214  * @param int $group_id ID of the group.
     1215 * @param int    $user_id  ID of the user.
     1216 * @param int    $group_id ID of the group.
     1217 * @param string $type     If 'sent', results are limited to those invitations
     1218 *                         that have actually been sent (non-draft).
     1219 *                         Possible values: 'sent', 'draft', or 'all' Default: 'sent'.
    12151220 * @return int|bool ID of the membership if the user is invited, otherwise false.
    12161221 */
    1217 function groups_is_user_invited( $user_id, $group_id ) {
    1218         $is_invited = false;
    1219 
    1220         $user_groups = bp_get_user_groups( $user_id, array(
    1221                 'invite_sent' => true,
    1222                 'is_confirmed' => false,
    1223         ) );
    1224 
    1225         if ( isset( $user_groups[ $group_id ] ) ) {
    1226                 $is_invited = $user_groups[ $group_id ]->id;
    1227         }
    1228 
    1229         return $is_invited;
     1222function groups_is_user_invited( $user_id, $group_id, $type = 'sent' ) {
     1223        return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
    12301224}
    12311225
    12321226/**
    function groups_is_user_invited( $user_id, $group_id ) { 
    12391233 * @return int|bool ID of the membership if the user is pending, otherwise false.
    12401234 */
    12411235function groups_is_user_pending( $user_id, $group_id ) {
    1242         $is_pending = false;
    1243 
    1244         $user_groups = bp_get_user_groups( $user_id, array(
    1245                 'invite_sent' => false,
    1246                 'is_confirmed' => false,
    1247         ) );
    1248 
    1249         if ( isset( $user_groups[ $group_id ] ) ) {
    1250                 $is_pending = $user_groups[ $group_id ]->id;
     1236        if ( empty( $user_id ) || empty( $group_id ) ) {
     1237                return false;
    12511238        }
    12521239
    1253         return $is_pending;
     1240        $args = array(
     1241                'user_id'     => $user_id,
     1242                'item_id'     => $group_id,
     1243        );
     1244        $invites_class = new BP_Groups_Invitations();
     1245
     1246        return $invites_class->request_exists( $args );
    12541247}
    12551248
    12561249/**
    function groups_post_update( $args = '' ) { 
    13621355/** Group Invitations *********************************************************/
    13631356
    13641357/**
    1365  * Get IDs of users with outstanding invites to a given group from a specified user.
     1358 * Get group objects for groups that a user is currently invited to.
    13661359 *
    13671360 * @since 1.0.0
    13681361 *
    1369  * @param int               $user_id ID of the inviting user.
     1362 * @param int               $user_id ID of the invited user.
    13701363 * @param int|bool          $limit   Limit to restrict to.
    13711364 * @param int|bool          $page    Optional. Page offset of results to return.
    13721365 * @param string|array|bool $exclude Array of comma-separated list of group IDs
    13731366 *                                   to exclude from results.
    1374  * @return array $value IDs of users who have been invited to the group by the
    1375  *                      user but have not yet accepted.
     1367 * @return array {
     1368 *     @type array $groups Array of groups returned by paginated query.
     1369 *     @type int   $total  Count of groups matching query.
     1370 * }
    13761371 */
    13771372function groups_get_invites_for_user( $user_id = 0, $limit = false, $page = false, $exclude = false ) {
    1378 
    1379         if ( empty( $user_id ) )
     1373        if ( empty( $user_id ) ) {
    13801374                $user_id = bp_loggedin_user_id();
     1375        }
     1376
     1377        $group_ids = groups_get_invited_to_group_ids( $user_id );
     1378
     1379        // Remove excluded groups.
     1380        if ( $exclude ) {
     1381                $group_ids = array_diff( $group_ids, wp_parse_id_list( $exclude ) );
     1382        }
    13811383
    1382         return BP_Groups_Member::get_invites( $user_id, $limit, $page, $exclude );
     1384        // Avoid passing an empty array.
     1385        if ( ! $group_ids ) {
     1386                $group_ids = array( 0 );
     1387        }
     1388
     1389        // Get a filtered list of groups.
     1390        $args = array(
     1391                'include'     => $group_ids,
     1392                'show_hidden' => true,
     1393                'per_page'    => $limit,
     1394                'page'        => $page,
     1395        );
     1396        $groups = groups_get_groups( $args );
     1397
     1398        return array( 'groups' => $groups['groups'], 'total' => groups_get_invite_count_for_user( $user_id ) );
    13831399}
    13841400
    13851401/**
    function groups_get_invite_count_for_user( $user_id = 0 ) { 
    13951411                $user_id = bp_loggedin_user_id();
    13961412        }
    13971413
    1398         return BP_Groups_Member::get_invite_count_for_user( $user_id );
     1414        return count( groups_get_invited_to_group_ids( $user_id ) );
     1415}
     1416
     1417/**
     1418 * Get an array of group IDs to which a user is invited.
     1419 *
     1420 * @since 5.0.0
     1421 *
     1422 * @param int $user_id The user ID.
     1423 *
     1424 * @return array Array of group IDs.
     1425 */
     1426 function groups_get_invited_to_group_ids( $user_id = 0 ) {
     1427        if ( empty( $user_id ) ) {
     1428                $user_id = bp_loggedin_user_id();
     1429        }
     1430
     1431        $group_ids = groups_get_invites( array(
     1432                'user_id'     => $user_id,
     1433                'invite_sent' => 'sent',
     1434                'fields'      => 'item_ids'
     1435        ) );
     1436
     1437        return array_unique( $group_ids );
    13991438}
    14001439
    14011440/**
    function groups_get_invite_count_for_user( $user_id = 0 ) { 
    14111450 *                                 ID of the logged-in user.
    14121451 *     @type string $date_modified Optional. Modified date for the invitation.
    14131452 *                                 Default: current date/time.
    1414  *     @type bool   $is_confirmed  Optional. Whether the invitation should be
    1415  *                                 marked confirmed. Default: false.
     1453 *     @type string $content       Optional. Message to invitee.
     1454 *     @type bool   $send_invite   Optional. Whether the invitation should be
     1455 *                                 sent now. Default: false.
    14161456 * }
    14171457 * @return bool True on success, false on failure.
    14181458 */
    14191459function groups_invite_user( $args = '' ) {
    14201460
    1421         $args = bp_parse_args( $args, array(
     1461        $r = bp_parse_args( $args, array(
    14221462                'user_id'       => false,
    14231463                'group_id'      => false,
    14241464                'inviter_id'    => bp_loggedin_user_id(),
    14251465                'date_modified' => bp_core_current_time(),
    1426                 'is_confirmed'  => 0
     1466                'content'       => '',
     1467                'send_invite'   => 0
    14271468        ), 'groups_invite_user' );
    1428         extract( $args, EXTR_SKIP );
    14291469
    1430         if ( ! $user_id || ! $group_id || ! $inviter_id ) {
    1431                 return false;
    1432         }
    1433 
    1434         // If the user has already requested membership, accept the request.
    1435         if ( $membership_id = groups_check_for_membership_request( $user_id, $group_id ) ) {
    1436                 groups_accept_membership_request( $membership_id, $user_id, $group_id );
    1437 
    1438         // Otherwise, create a new invitation.
    1439         } elseif ( ! groups_is_user_member( $user_id, $group_id ) && ! groups_check_user_has_invite( $user_id, $group_id, 'all' ) ) {
    1440                 $invite                = new BP_Groups_Member;
    1441                 $invite->group_id      = $group_id;
    1442                 $invite->user_id       = $user_id;
    1443                 $invite->date_modified = $date_modified;
    1444                 $invite->inviter_id    = $inviter_id;
    1445                 $invite->is_confirmed  = $is_confirmed;
     1470        $inv_args = array(
     1471                'user_id'       => $r['user_id'],
     1472                'item_id'       => $r['group_id'],
     1473                'inviter_id'    => $r['inviter_id'],
     1474                'date_modified' => $r['date_modified'],
     1475                'content'       => $r['content'],
     1476                'send_invite'   => $r['send_invite']
     1477        );
    14461478
    1447                 if ( !$invite->save() )
    1448                         return false;
     1479        // Create the unsent invitataion.
     1480        $invites_class = new BP_Groups_Invitations();
     1481        $created       = $invites_class->add_invitation( $inv_args );
    14491482
    1450                 /**
    1451                 * Fires after the creation of a new group invite.
    1452                 *
    1453                 * @since 1.0.0
    1454                 *
    1455                  * @param array $args Array of parsed arguments for the group invite.
    1456                  */
    1457                 do_action( 'groups_invite_user', $args );
    1458         }
     1483        /**
     1484        * Fires after the creation of a new group invite.
     1485        *
     1486        * @since 1.0.0
     1487        *
     1488         * @param array    $r      Array of parsed arguments for the group invite.
     1489         * @param int|bool $created The ID of the invitation or false if it couldn't be created.
     1490         */
     1491        do_action( 'groups_invite_user', $r, $created );
    14591492
    1460         return true;
     1493        return $created;
    14611494}
    14621495
    14631496/**
    function groups_invite_user( $args = '' ) { 
    14691502 *
    14701503 * @param int $user_id  ID of the user.
    14711504 * @param int $group_id ID of the group.
     1505 * @param int $inviter_id ID of the inviter.
    14721506 * @return bool True on success, false on failure.
    14731507 */
    1474 function groups_uninvite_user( $user_id, $group_id ) {
    1475 
    1476         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1508function groups_uninvite_user( $user_id, $group_id, $inviter_id = false ) {
     1509        if ( empty( $user_id ) || empty( $group_id ) ) {
    14771510                return false;
     1511        }
    14781512
    1479         /**
    1480          * Fires after uninviting a user from a group.
    1481          *
    1482          * @since 1.0.0
    1483          *
    1484          * @param int $group_id ID of the group being uninvited from.
    1485          * @param int $user_id  ID of the user being uninvited.
    1486          */
    1487         do_action( 'groups_uninvite_user', $group_id, $user_id );
     1513        $invites_class = new BP_Groups_Invitations();
     1514        $success       = $invites_class->delete( array(
     1515                'user_id'    => $user_id,
     1516                'item_id'    => $group_id,
     1517                'inviter_id' => $inviter_id,
     1518        ) );
    14881519
    1489         return true;
     1520        if ( $success ) {
     1521                /**
     1522                 * Fires after uninviting a user from a group.
     1523                 *
     1524                 * @since 1.0.0
     1525                 * @since 2.7.0 Added $inviter_id parameter
     1526                 *
     1527                 * @param int $group_id    ID of the group being uninvited from.
     1528                 * @param int $user_id     ID of the user being uninvited.
     1529                 * @param int $inviter_id  ID of the inviter.
     1530                 */
     1531                do_action( 'groups_uninvite_user', $group_id, $user_id, $inviter_id );
     1532        }
     1533
     1534        return $success;
    14901535}
    14911536
    14921537/**
    function groups_uninvite_user( $user_id, $group_id ) { 
    15011546 * @return bool True when the user is a member of the group, otherwise false.
    15021547 */
    15031548function groups_accept_invite( $user_id, $group_id ) {
     1549        $invites_class = new BP_Groups_Invitations();
     1550        $args = array(
     1551                'user_id'     => $user_id,
     1552                'item_id'     => $group_id,
     1553                'invite_sent' => 'sent',
     1554        );
     1555        // Get an inviter_id from the invitation.
     1556        $invites = groups_get_invites( $args );
     1557        $inviter_id = 0;
     1558        if ( $invites ) {
     1559                $inviter_id = current( $invites )->inviter_id;
     1560        }
    15041561
    1505         // If the user is already a member (because BP at one point allowed two invitations to
    1506         // slip through), delete all existing invitations/requests and return true.
    1507         if ( groups_is_user_member( $user_id, $group_id ) ) {
    1508                 if ( groups_check_user_has_invite( $user_id, $group_id ) ) {
    1509                         groups_delete_invite( $user_id, $group_id );
    1510                 }
    1511 
    1512                 if ( groups_check_for_membership_request( $user_id, $group_id ) ) {
    1513                         groups_delete_membership_request( null, $user_id, $group_id );
    1514                 }
    1515 
    1516                 return true;
    1517         }
    1518 
    1519         $member = new BP_Groups_Member( $user_id, $group_id );
    1520 
    1521         // Save the inviter ID so that we can pass it to the action below.
    1522         $inviter_id = $member->inviter_id;
    1523 
    1524         $member->accept_invite();
    1525 
    1526         if ( !$member->save() ) {
    1527                 return false;
    1528         }
    1529 
    1530         // Remove request to join.
    1531         if ( $member->check_for_membership_request( $user_id, $group_id ) ) {
    1532                 $member->delete_request( $user_id, $group_id );
    1533         }
    1534 
    1535         // Modify group meta.
    1536         groups_update_groupmeta( $group_id, 'last_activity', bp_core_current_time() );
     1562        $invites_class->accept_invitation( $args );
    15371563
    15381564        /**
    15391565         * Fires after a user has accepted a group invite.
    function groups_accept_invite( $user_id, $group_id ) { 
    15541580 * Reject a group invitation.
    15551581 *
    15561582 * @since 1.0.0
     1583 * @since 5.0.0 The $inviter_id arg was added.
     1584 *
     1585 * @param int $user_id    ID of the user.
     1586 * @param int $group_id   ID of the group.
     1587 * @param int $inviter_id ID of the inviter.
    15571588 *
    1558  * @param int $user_id  ID of the user.
    1559  * @param int $group_id ID of the group.
    15601589 * @return bool True on success, false on failure.
    15611590 */
    1562 function groups_reject_invite( $user_id, $group_id ) {
    1563         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1591function groups_reject_invite( $user_id, $group_id, $inviter_id = false ) {
     1592        if ( empty( $user_id ) || empty( $group_id ) ) {
    15641593                return false;
     1594        }
     1595
     1596        $invites_class = new BP_Groups_Invitations();
     1597        $success       = $invites_class->delete( array(
     1598                'user_id'    => $user_id,
     1599                'item_id'    => $group_id,
     1600                'inviter_id' => $inviter_id,
     1601        ) );
    15651602
    15661603        /**
    15671604         * Fires after a user rejects a group invitation.
    15681605         *
    15691606         * @since 1.0.0
     1607         * @since 5.0.0 The $inviter_id arg was added.
    15701608         *
    15711609         * @param int $user_id  ID of the user rejecting the invite.
    15721610         * @param int $group_id ID of the group being rejected.
     1611         * @param int $inviter_id ID of the inviter.
    15731612         */
    1574         do_action( 'groups_reject_invite', $user_id, $group_id );
     1613        do_action( 'groups_reject_invite', $user_id, $group_id, $inviter_id );
    15751614
    1576         return true;
     1615        return $success;
    15771616}
    15781617
    15791618/**
    15801619 * Delete a group invitation.
    15811620 *
    15821621 * @since 1.0.0
     1622 * @since 5.0.0 The $inviter_id arg was added.
    15831623 *
    15841624 * @param int $user_id  ID of the invited user.
    15851625 * @param int $group_id ID of the group.
     1626 * @param int $inviter_id ID of the inviter.
     1627 *
    15861628 * @return bool True on success, false on failure.
    15871629 */
    1588 function groups_delete_invite( $user_id, $group_id ) {
    1589         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1630function groups_delete_invite( $user_id, $group_id, $inviter_id = false ) {
     1631        if ( empty( $user_id ) || empty( $group_id ) ) {
    15901632                return false;
     1633        }
     1634
     1635        $invites_class = new BP_Groups_Invitations();
     1636        $success       = $invites_class->delete( array(
     1637                'user_id'    => $user_id,
     1638                'item_id'    => $group_id,
     1639                'inviter_id' => $inviter_id,
     1640        ) );
    15911641
    15921642        /**
    15931643         * Fires after the deletion of a group invitation.
    15941644         *
    15951645         * @since 1.9.0
     1646         * @since 5.0.0 The $inviter_id arg was added.
    15961647         *
    15971648         * @param int $user_id  ID of the user whose invitation is being deleted.
    15981649         * @param int $group_id ID of the group whose invitation is being deleted.
     1650         * @param int $inviter_id ID of the inviter.
    15991651         */
    1600         do_action( 'groups_delete_invite', $user_id, $group_id );
     1652        do_action( 'groups_delete_invite', $user_id, $group_id, $inviter_id );
    16011653
    16021654        return true;
    16031655}
    16041656
    16051657/**
    1606  * Send all pending invites by a single user to a specific group.
     1658 * Send some or all pending invites by a single user to a specific group.
    16071659 *
    16081660 * @since 1.0.0
     1661 * @since 5.0.0 Parameters changed to associative array.
    16091662 *
    1610  * @param int $user_id  ID of the inviting user.
    1611  * @param int $group_id ID of the group.
     1663 * @param array $args {
     1664 *     An array of optional arguments.
     1665 *     @type int    $user_id       ID of the invited user.
     1666 *     @type string $invitee_email Email address of the invited user, if not a member of the site.
     1667 *     @type string $group_id      ID of the group or an array of group IDs.
     1668 *     @type string $inviter_id    ID of the user extending the invitation.
     1669 *     @type bool   $force_resend  Whether to resend the email & notification if one has already been sent.
     1670 * }
    16121671 */
    1613 function groups_send_invites( $user_id, $group_id ) {
     1672function groups_send_invites( $args = array() ) {
     1673        // Backward compatibility with old method of passing arguments.
     1674        if ( ! is_array( $args ) || func_num_args() > 1 ) {
     1675                _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
    16141676
    1615         if ( empty( $user_id ) )
    1616                 $user_id = bp_loggedin_user_id();
     1677                $old_args_keys = array(
     1678                        0 => 'inviter_id',
     1679                        1 => 'group_id',
     1680                );
    16171681
    1618         // Send friend invites.
    1619         $invited_users = groups_get_invites_for_group( $user_id, $group_id );
    1620         $group = groups_get_group( $group_id );
     1682                $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
     1683        }
    16211684
    1622         for ( $i = 0, $count = count( $invited_users ); $i < $count; ++$i ) {
    1623                 $member = new BP_Groups_Member( $invited_users[$i], $group_id );
     1685        $r = bp_parse_args( $args, array(
     1686                'user_id'       => false,
     1687                'invitee_email' => '',
     1688                'group_id'      => 0,
     1689                'inviter_id'    => bp_loggedin_user_id(),
     1690                'force_resend'  => false,
     1691        ), 'groups_send_invitation' );
    16241692
    1625                 // Skip if we've already sent an invite to this user.
    1626                 if ( $member->invite_sent ) {
    1627                         continue;
    1628                 }
     1693        /*
     1694         * We will generally only want to fetch unsent invitations.
     1695         * If force_resend is true, then we need to fetch both sent and draft invites.
     1696         */
     1697        if ( $r['force_resend'] ) {
     1698                $args['invite_sent'] = 'all';
     1699        } else {
     1700                $args['invite_sent'] = 'draft';
     1701        }
    16291702
    1630                 // Send the actual invite.
    1631                 groups_notification_group_invites( $group, $member, $user_id );
     1703        $args = array(
     1704                'user_id'       => $r['user_id'],
     1705                'invitee_email' => $r['invitee_email'],
     1706                'item_id'       => $r['group_id'],
     1707                'inviter_id'    => $r['inviter_id'],
     1708        );
     1709        $invites = groups_get_invites( $args );
    16321710
    1633                 $member->invite_sent = 1;
    1634                 $member->save();
     1711        $invited_users = array();
     1712
     1713        $invites_class = new BP_Groups_Invitations();
     1714        foreach ( $invites as $invite ) {
     1715                $invited_users[] = $invite->user_id;
     1716                $invites_class->send_invitation_by_id( $invite->id );
    16351717        }
    16361718
    16371719        /**
    function groups_send_invites( $user_id, $group_id ) { 
    16441726         * @param array $invited_users Array of users being invited to the group.
    16451727         * @param int   $user_id       ID of the inviting user.
    16461728         */
    1647         do_action( 'groups_send_invites', $group_id, $invited_users, $user_id );
     1729        do_action( 'groups_send_invites', $r['group_id'], $invited_users, $r['inviter_id'] );
    16481730}
    16491731
    16501732/**
    1651  * Get IDs of users with outstanding invites to a given group from a specified user.
     1733 * Get IDs of users with outstanding invites to a given group.
    16521734 *
    16531735 * @since 1.0.0
    16541736 * @since 2.9.0 Added $sent as a parameter.
    function groups_get_invites_for_group( $user_id, $group_id, $sent = null ) { 
    16661748        return BP_Groups_Group::get_invites( $user_id, $group_id, $sent );
    16671749}
    16681750
     1751/**
     1752 * Get invitations to a given group filtered by arguments.
     1753 *
     1754 * @since 5.0.0
     1755 *
     1756 * @param int   $group_id ID of the group.
     1757 * @param array $args     Invitation arguments.
     1758 *                        See BP_Invitations_Invitation::get() for list.
     1759 *
     1760 * @return array $invites     Matching BP_Invitations_Invitation objects.
     1761 */
     1762function groups_get_invites( $args = array() ) {
     1763        $invites_class = new BP_Groups_Invitations();
     1764        return $invites_class->get_invitations( $args );
     1765}
     1766
    16691767/**
    16701768 * Check to see whether a user has already been invited to a group.
    16711769 *
    function groups_get_invites_for_group( $user_id, $group_id, $sent = null ) { 
    16791777 * @param int    $group_id ID of potential group.
    16801778 * @param string $type     Optional. Use 'sent' to check for sent invites,
    16811779 *                         'all' to check for all. Default: 'sent'.
    1682  * @return int|bool ID of the membership if found, otherwise false.
     1780 * @return int|bool ID of the first found membership if found, otherwise false.
    16831781 */
    16841782function groups_check_user_has_invite( $user_id, $group_id, $type = 'sent' ) {
    1685         $invite = false;
     1783        return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
     1784}
     1785
     1786/**
     1787 * Check to see whether a user has already been invited to a group by a particular user.
     1788 *
     1789 * By default, the function checks for invitations that have been sent.
     1790 * Entering 'all' as the $type parameter will return unsent invitations as
     1791 * well (useful to make sure AJAX requests are not duplicated).
     1792 *
     1793 * @since 5.0.0
     1794 *
     1795 * @param int    $user_id    ID of potential group member.
     1796 * @param int    $group_id   ID of potential group.
     1797 * @param string $inviter_id Optional. Use 'sent' to check for sent invites,
     1798 *                           'all' to check for all. Default: 'sent'.
     1799 * @param string $type       Optional. Specify a user ID to limit to only invited from that user.
     1800 *                           Default: 'false'.
     1801 * @return int|bool ID of the first found membership if found, otherwise false.
     1802 */
     1803 function groups_check_has_invite_from_user( $user_id, $group_id, $inviter_id = false, $type = 'sent' ) {
     1804        if ( empty( $user_id ) || empty( $group_id ) ) {
     1805                return false;
     1806        }
    16861807
    16871808        $args = array(
    1688                 'is_confirmed' => false,
    1689                 'is_banned'    => null,
    1690                 'is_admin'     => null,
    1691                 'is_mod'       => null,
     1809                'user_id'     => $user_id,
     1810                'item_id'     => $group_id,
     1811                'invite_sent' => 'sent',
    16921812        );
    1693 
    1694         if ( 'sent' === $type ) {
    1695                 $args['invite_sent'] = true;
     1813        if ( $inviter_id ) {
     1814                $args['inviter_id'] = $inviter_id;
    16961815        }
    1697 
    1698         $user_groups = bp_get_user_groups( $user_id, $args );
    1699 
    1700         if ( isset( $user_groups[ $group_id ] ) && 0 !== $user_groups[ $group_id ]->inviter_id ) {
    1701                 $invite = $user_groups[ $group_id ]->id;
     1816        if ( $type === 'draft' || $type === 'all' ) {
     1817                $args['invite_sent'] = $type;
    17021818        }
    17031819
    1704         return $invite;
     1820        $invites_class = new BP_Groups_Invitations();
     1821
     1822        return $invites_class->invitation_exists( $args );
    17051823}
    17061824
    17071825/**
    function groups_remove_member( $user_id, $group_id ) { 
    18781996 *
    18791997 * @since 1.0.0
    18801998 *
    1881  * @param int $requesting_user_id ID of the user requesting membership.
    1882  * @param int $group_id           ID of the group.
     1999 * @param array|string $args {
     2000 *     Array of arguments.
     2001 *     @type int    $user_id       ID of the user being invited.
     2002 *     @type int    $group_id      ID of the group to which the user is being invited.
     2003 *     @type string $content       Optional. Message to invitee.
     2004 *     @type string $date_modified Optional. Modified date for the invitation.
     2005 *                                 Default: current date/time.
     2006 * }
    18832007 * @return bool True on success, false on failure.
    18842008 */
    1885 function groups_send_membership_request( $requesting_user_id, $group_id ) {
    1886 
    1887         // Prevent duplicate requests.
    1888         if ( groups_check_for_membership_request( $requesting_user_id, $group_id ) )
    1889                 return false;
     2009function groups_send_membership_request( $args = array() ) {
     2010        // Backward compatibility with old method of passing arguments.
     2011        if ( ! is_array( $args ) || func_num_args() > 1 ) {
     2012                _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
    18902013
    1891         // Check if the user is already a member or is banned.
    1892         if ( groups_is_user_member( $requesting_user_id, $group_id ) || groups_is_user_banned( $requesting_user_id, $group_id ) )
    1893                 return false;
     2014                $old_args_keys = array(
     2015                        0 => 'user_id',
     2016                        1 => 'group_id',
     2017                );
    18942018
    1895         // Check if the user is already invited - if so, simply accept invite.
    1896         if ( groups_check_user_has_invite( $requesting_user_id, $group_id ) ) {
    1897                 groups_accept_invite( $requesting_user_id, $group_id );
    1898                 return true;
     2019                $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
    18992020        }
    19002021
    1901         $requesting_user                = new BP_Groups_Member;
    1902         $requesting_user->group_id      = $group_id;
    1903         $requesting_user->user_id       = $requesting_user_id;
    1904         $requesting_user->inviter_id    = 0;
    1905         $requesting_user->is_admin      = 0;
    1906         $requesting_user->user_title    = '';
    1907         $requesting_user->date_modified = bp_core_current_time();
    1908         $requesting_user->is_confirmed  = 0;
    1909         $requesting_user->comments      = isset( $_POST['group-request-membership-comments'] ) ? $_POST['group-request-membership-comments'] : '';
     2022        $r = bp_parse_args( $args, array(
     2023                'user_id'       => false,
     2024                'group_id'      => false,
     2025                'content'       => '',
     2026                'date_modified' => bp_core_current_time(),
     2027        ), 'groups_invite_user' );
    19102028
    1911         if ( $requesting_user->save() ) {
    1912                 $admins = groups_get_group_admins( $group_id );
     2029        $inv_args = array(
     2030                'user_id'       => $r['user_id'],
     2031                'item_id'       => $r['group_id'],
     2032                'content'       => $r['content'],
     2033                'date_modified' => $r['date_modified'],
     2034        );
     2035
     2036        $invites_class = new BP_Groups_Invitations();
     2037        $request_id = $invites_class->add_request( $inv_args );
    19132038
    1914                 // Saved okay, now send the email notification.
    1915                 for ( $i = 0, $count = count( $admins ); $i < $count; ++$i )
    1916                         groups_notification_new_membership_request( $requesting_user_id, $admins[$i]->user_id, $group_id, $requesting_user->id );
     2039        // If a new request was created, send the emails.
     2040        if ( $request_id && is_int( $request_id ) ) {
     2041                $invites_class->send_request_notification_by_id( $request_id );
     2042                $admins = groups_get_group_admins( $r['group_id'] );
    19172043
    19182044                /**
    19192045                 * Fires after the creation of a new membership request.
    function groups_send_membership_request( $requesting_user_id, $group_id ) { 
    19232049                 * @param int   $requesting_user_id  ID of the user requesting membership.
    19242050                 * @param array $admins              Array of group admins.
    19252051                 * @param int   $group_id            ID of the group being requested to.
    1926                  * @param int   $requesting_user->id ID of the membership.
     2052                 * @param int   $request_id          ID of the request.
    19272053                 */
    1928                 do_action( 'groups_membership_requested', $requesting_user_id, $admins, $group_id, $requesting_user->id );
     2054                do_action( 'groups_membership_requested', $r['user_id'], $admins, $r['group_id'], $request_id );
    19292055
    1930                 return true;
     2056                return $request_id;
    19312057        }
    19322058
    19332059        return false;
    function groups_send_membership_request( $requesting_user_id, $group_id ) { 
    19372063 * Accept a pending group membership request.
    19382064 *
    19392065 * @since 1.0.0
     2066 * @since 5.0.0 Deprecated $membership_id argument.
    19402067 *
    1941  * @param int $membership_id ID of the membership object.
    1942  * @param int $user_id       Optional. ID of the user who requested membership.
     2068 * @param int $membership_id Deprecated 5.0.0.
     2069 * @param int $user_id       Required. ID of the user who requested membership.
    19432070 *                           Provide this value along with $group_id to override
    19442071 *                           $membership_id.
    1945  * @param int $group_id      Optional. ID of the group to which membership is being
     2072 * @param int $group_id      Required. ID of the group to which membership is being
    19462073 *                           requested. Provide this value along with $user_id to
    19472074 *                           override $membership_id.
    19482075 * @return bool True on success, false on failure.
    19492076 */
    19502077function groups_accept_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    19512078
    1952         if ( !empty( $user_id ) && !empty( $group_id ) ) {
    1953                 $membership = new BP_Groups_Member( $user_id, $group_id );
    1954         } else {
    1955                 $membership = new BP_Groups_Member( false, false, $membership_id );
     2079        if ( ! empty( $membership_id ) ) {
     2080                _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s  is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
    19562081        }
    19572082
    1958         $membership->accept_request();
    1959 
    1960         if ( !$membership->save() ) {
     2083        if ( ! $user_id || ! $group_id ) {
    19612084                return false;
    19622085        }
    19632086
    1964         // Check if the user has an outstanding invite, if so delete it.
    1965         if ( groups_check_user_has_invite( $membership->user_id, $membership->group_id ) ) {
    1966                 groups_delete_invite( $membership->user_id, $membership->group_id );
    1967         }
     2087        $invites_class = new BP_Groups_Invitations();
     2088        $args = array(
     2089                'user_id' => $user_id,
     2090                'item_id' => $group_id,
     2091        );
     2092        $invites_class->accept_request( $args );
    19682093
    19692094        /**
    19702095         * Fires after a group membership request has been accepted.
    function groups_accept_membership_request( $membership_id, $user_id = 0, $group_ 
    19752100         * @param int  $group_id ID of the group that was accepted membership to.
    19762101         * @param bool $value    If membership was accepted.
    19772102         */
    1978         do_action( 'groups_membership_accepted', $membership->user_id, $membership->group_id, true );
     2103        do_action( 'groups_membership_accepted', $user_id, $group_id, true );
    19792104
    19802105        return true;
    19812106}
    function groups_accept_membership_request( $membership_id, $user_id = 0, $group_ 
    19852110 *
    19862111 * @since 1.0.0
    19872112 *
    1988  * @param int $membership_id ID of the membership object.
     2113 * @param int $membership_id Deprecated 5.0.0.
    19892114 * @param int $user_id       Optional. ID of the user who requested membership.
    19902115 *                           Provide this value along with $group_id to override
    19912116 *                           $membership_id.
    function groups_accept_membership_request( $membership_id, $user_id = 0, $group_ 
    19952120 * @return bool True on success, false on failure.
    19962121 */
    19972122function groups_reject_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    1998         if ( !$membership = groups_delete_membership_request( $membership_id, $user_id, $group_id ) ) {
     2123
     2124        if ( ! empty( $membership_id ) ){
     2125                _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s  is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
     2126        }
     2127
     2128        if ( ! groups_delete_membership_request( false, $user_id, $group_id ) ) {
    19992129                return false;
    20002130        }
    20012131
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    20082138         * @param int  $group_id ID of the group that was rejected membership to.
    20092139         * @param bool $value    If membership was accepted.
    20102140         */
    2011         do_action( 'groups_membership_rejected', $membership->user_id, $membership->group_id, false );
     2141        do_action( 'groups_membership_rejected', $user_id, $group_id, false );
    20122142
    20132143        return true;
    20142144}
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    20182148 *
    20192149 * @since 1.2.0
    20202150 *
    2021  * @param int $membership_id ID of the membership object.
     2151 * @param int $membership_id Deprecated 5.0.0.
    20222152 * @param int $user_id       Optional. ID of the user who requested membership.
    20232153 *                           Provide this value along with $group_id to override
    20242154 *                           $membership_id.
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    20282158 * @return false|BP_Groups_Member True on success, false on failure.
    20292159 */
    20302160function groups_delete_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    2031         if ( !empty( $user_id ) && !empty( $group_id ) )
    2032                 $membership = new BP_Groups_Member( $user_id, $group_id );
    2033         else
    2034                 $membership = new BP_Groups_Member( false, false, $membership_id );
     2161        if ( ! empty( $membership_id ) ){
     2162                _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s  is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
     2163        }
    20352164
    2036         if ( ! BP_Groups_Member::delete_request( $membership->user_id, $membership->group_id ) )
     2165        if ( empty( $user_id ) || empty( $group_id ) ) {
    20372166                return false;
     2167        }
     2168
     2169        $invites_class = new BP_Groups_Invitations();
     2170        $success       = $invites_class->delete_requests( array(
     2171                'user_id' => $user_id,
     2172                'item_id' => $group_id
     2173        ) );
    20382174
    2039         return $membership;
     2175        return $success;
     2176}
     2177
     2178/**
     2179 * Get group membership requests filtered by arguments.
     2180 *
     2181 * @since 5.0.0
     2182 *
     2183 * @param int   $group_id ID of the group.
     2184 * @param array $args     Invitation arguments.
     2185 *                        See BP_Invitations_Invitation::get() for list.
     2186 *
     2187 * @return array $requests Matching BP_Invitations_Invitation objects.
     2188 */
     2189function groups_get_requests( $args = array() ) {
     2190        $invites_class = new BP_Groups_Invitations();
     2191        return $invites_class->get_requests( $args );
    20402192}
    20412193
    20422194/**
    function groups_delete_membership_request( $membership_id, $user_id = 0, $group_ 
    20462198 *
    20472199 * @param int $user_id  ID of the user.
    20482200 * @param int $group_id ID of the group.
    2049  * @return int|bool ID of the membership if found, otherwise false.
     2201 * @return int|bool ID of the request if found, otherwise false.
    20502202 */
    20512203function groups_check_for_membership_request( $user_id, $group_id ) {
    2052         $request = false;
     2204        if ( empty( $user_id ) || empty( $group_id ) ) {
     2205                return false;
     2206        }
    20532207
    2054         $user_groups = bp_get_user_groups( $user_id, array(
    2055                 'is_confirmed' => false,
    2056                 'is_banned'    => false,
    2057                 'is_admin'     => null,
    2058                 'is_mod'       => null
     2208        $args = array(
     2209                'user_id' => $user_id,
     2210                'item_id' => $group_id,
     2211        );
     2212        $invites_class = new BP_Groups_Invitations();
     2213
     2214        return $invites_class->request_exists( $args );
     2215}
     2216
     2217 /**
     2218  * Get an array of group IDs to which a user has requested membership.
     2219  *
     2220  * @since 5.0.0
     2221  *
     2222  * @param int $user_id The user ID.
     2223  *
     2224  * @return array Array of group IDs.
     2225  */
     2226 function groups_get_membership_requested_group_ids( $user_id = 0 ) {
     2227        if ( ! $user_id ) {
     2228                $user_id = bp_loggedin_user_id();
     2229        }
     2230
     2231        $group_ids     = groups_get_requests( array(
     2232                'user_id' => $user_id,
     2233                'fields'  => 'item_ids'
    20592234        ) );
    20602235
    2061         if ( isset( $user_groups[ $group_id ] ) && 0 === $user_groups[ $group_id ]->inviter_id ) {
    2062                 $request = $user_groups[ $group_id ]->id;
    2063         }
     2236        return $group_ids;
     2237}
     2238
     2239 /**
     2240  * Get an array of group IDs to which a user has requested membership.
     2241  *
     2242  * @since 5.0.0
     2243  *
     2244  * @param int $user_id The user ID.
     2245  *
     2246  * @return array Array of group IDs.
     2247  */
     2248 function groups_get_membership_requested_user_ids( $group_id = 0 ) {
     2249        if ( ! $group_id ) {
     2250                $group_id = bp_get_current_group_id();
     2251        }
     2252
     2253        $requests      = groups_get_requests( array(
     2254                'item_id' => $group_id,
     2255                'fields'  => 'user_ids'
     2256        ) );
    20642257
    2065         return $request;
     2258        //@TODO-6210: What about those who make a request by email only (not yet site members)?
     2259        return $requests;
    20662260}
    20672261
    20682262/**
    function groups_check_for_membership_request( $user_id, $group_id ) { 
    20732267 * @param int $group_id ID of the group.
    20742268 * @return bool True on success, false on failure.
    20752269 */
    2076 function groups_accept_all_pending_membership_requests( $group_id ) {
    2077         $user_ids = BP_Groups_Member::get_all_membership_request_user_ids( $group_id );
     2270function groups_accept_all_pending_membership_requests( $group_id = 0 ) {
     2271        if ( ! $group_id ) {
     2272                $group_id = bp_get_current_group_id();
     2273        }
    20782274
    2079         if ( !$user_ids )
     2275        $user_ids = groups_get_membership_requested_user_ids( $group_id );
     2276
     2277        if ( ! $user_ids ) {
    20802278                return false;
     2279        }
    20812280
    2082         foreach ( (array) $user_ids as $user_id )
     2281        foreach ( (array) $user_ids as $user_id ) {
    20832282                groups_accept_membership_request( false, $user_id, $group_id );
     2283        }
    20842284
    20852285        /**
    20862286         * Fires after the acceptance of all pending membership requests to a group.
    function bp_groups_pending_requests_personal_data_exporter( $email_address, $pag 
    27562956                );
    27572957        }
    27582958
    2759         $requests = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2760                 'type'     => 'pending_request',
     2959        $requests = groups_get_requests( array(
     2960                'user_id'  => $user->ID,
    27612961                'page'     => $page,
    27622962                'per_page' => $number,
    27632963        ) );
    27642964
    27652965        foreach ( $requests as $request ) {
    2766                 $group = groups_get_group( $request->group_id );
     2966                $group = groups_get_group( $request->item_id );
    27672967
    27682968                $item_data = array(
    27692969                        array(
    function bp_groups_pending_sent_invitations_personal_data_exporter( $email_addre 
    28223022                );
    28233023        }
    28243024
    2825         $invitations = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2826                 'type'     => 'pending_sent_invitation',
    2827                 'page'     => $page,
    2828                 'per_page' => $number,
     3025        $invitations = groups_get_invites( array(
     3026                'inviter_id'  => $user->ID,
     3027                'page'        => $page,
     3028                'per_page'    => $number,
    28293029        ) );
    28303030
    28313031        foreach ( $invitations as $invitation ) {
    2832                 $group = groups_get_group( $invitation->group_id );
     3032                $group = groups_get_group( $invitation->item_id );
    28333033
    28343034                $item_data = array(
    28353035                        array(
    function bp_groups_pending_received_invitations_personal_data_exporter( $email_a 
    28923092                );
    28933093        }
    28943094
    2895         $invitations = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2896                 'type'     => 'pending_received_invitation',
     3095        $invitations = groups_get_invites( array(
     3096                'user_id'  => $user->ID,
    28973097                'page'     => $page,
    28983098                'per_page' => $number,
    28993099        ) );
    29003100
    29013101        foreach ( $invitations as $invitation ) {
    2902                 $group = groups_get_group( $invitation->group_id );
     3102                $group = groups_get_group( $invitation->item_id );
    29033103
    29043104                $item_data = array(
    29053105                        array(
  • src/bp-groups/bp-groups-notifications.php

    diff --git src/bp-groups/bp-groups-notifications.php src/bp-groups/bp-groups-notifications.php
    index b94850fb5..481c70770 100644
    function groups_notification_new_membership_request( $requesting_user_id = 0, $a 
    143143                'notification_type' => 'groups-membership-request',
    144144        );
    145145
     146        $request_message = '';
     147        $requests = groups_get_requests( $args = array(
     148                'user_id'    => $requesting_user_id,
     149                'item_id'    => $group_id,
     150        ) );
     151        if ( $requests ) {
     152                $request_message = current( $requests )->content;
     153        }
     154
    146155        $group = groups_get_group( $group_id );
    147156        $args  = array(
    148157                'tokens' => array(
    function groups_notification_new_membership_request( $requesting_user_id = 0, $a 
    151160                        'group.name'           => $group->name,
    152161                        'group.id'             => $group_id,
    153162                        'group-requests.url'   => esc_url( bp_get_group_permalink( $group ) . 'admin/membership-requests' ),
    154                         'membership.id'        => $membership_id,
    155163                        'profile.url'          => esc_url( bp_core_get_user_domain( $requesting_user_id ) ),
    156164                        'requesting-user.id'   => $requesting_user_id,
    157165                        'requesting-user.name' => bp_core_get_user_displayname( $requesting_user_id ),
     166                        'request.message'      => $request_message,
    158167                        'unsubscribe'          => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
    159168                ),
    160169        );
    add_action( 'groups_promoted_member', 'groups_notification_promoted_member', 10, 
    289298 *
    290299 * @since 1.0.0
    291300 *
    292  * @param BP_Groups_Group  $group           Group object.
    293  * @param BP_Groups_Member $member          Member object.
    294  * @param int              $inviter_user_id ID of the user who sent the invite.
     301 * @param BP_Groups_Group      $group           Group object.
     302 * @param BP_Groups_Member|int $member          Member object or invited_user_id.
     303 * @param int                  $inviter_user_id ID of the user who sent the invite.
    295304 */
    296305function groups_notification_group_invites( &$group, &$member, $inviter_user_id ) {
    297306
    298         // Bail if member has already been invited.
    299         if ( ! empty( $member->invite_sent ) ) {
    300                 return;
    301         }
    302 
    303307        // @todo $inviter_ud may be used for caching, test without it
    304308        $inviter_ud      = bp_core_get_core_userdata( $inviter_user_id );
    305         $invited_user_id = $member->user_id;
     309
     310        if ( $member instanceof BP_Groups_Member ) {
     311                $invited_user_id = $member->user_id;
     312        } else if ( is_int( $member ) ) {
     313                $invited_user_id = $member;
     314        }
    306315
    307316        // Trigger a BuddyPress Notification.
    308317        if ( bp_is_active( 'notifications' ) ) {
    function groups_notification_group_invites( &$group, &$member, $inviter_user_id 
    326335                'notification_type' => 'groups-invitation',
    327336        );
    328337
     338        $invite_message = '';
     339        $invitations = groups_get_invites( $args = array(
     340                'user_id'    => $invited_user_id,
     341                'item_id'    => $group->id,
     342                'inviter_id' => $inviter_user_id,
     343        ) );
     344        if ( $invitations ) {
     345                $invite_message = current( $invitations )->content;
     346        }
     347
    329348        $args         = array(
    330349                'tokens' => array(
    331                         'group'        => $group,
    332                         'group.url'    => bp_get_group_permalink( $group ),
    333                         'group.name'   => $group->name,
    334                         'inviter.name' => bp_core_get_userlink( $inviter_user_id, true, false, true ),
    335                         'inviter.url'  => bp_core_get_user_domain( $inviter_user_id ),
    336                         'inviter.id'   => $inviter_user_id,
    337                         'invites.url'  => esc_url( $invited_link . '/invites/' ),
    338                         'unsubscribe'  => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
     350                        'group'          => $group,
     351                        'group.url'      => bp_get_group_permalink( $group ),
     352                        'group.name'     => $group->name,
     353                        'inviter.name'   => bp_core_get_userlink( $inviter_user_id, true, false, true ),
     354                        'inviter.url'    => bp_core_get_user_domain( $inviter_user_id ),
     355                        'inviter.id'     => $inviter_user_id,
     356                        'invites.url'    => esc_url( $invited_link . '/invites/' ),
     357                        'invite.message' => $invite_message,
     358                        'unsubscribe'    => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
    339359                ),
    340360        );
     361
    341362        bp_send_email( 'groups-invitation', (int) $invited_user_id, $args );
    342363}
    343364
  • src/bp-groups/bp-groups-template.php

    diff --git src/bp-groups/bp-groups-template.php src/bp-groups/bp-groups-template.php
    index c5c5a0465..710830c33 100644
    function bp_group_request_reject_link() { 
    54375437                 *
    54385438                 * @param string $value URL to use to reject a membership request.
    54395439                 */
    5440                 return apply_filters( 'bp_get_group_request_reject_link', wp_nonce_url( trailingslashit( bp_get_group_permalink( groups_get_current_group() ) . 'admin/membership-requests/reject/' . $requests_template->request->membership_id ), 'groups_reject_membership_request' ) );
     5440                return apply_filters( 'bp_get_group_request_reject_link', wp_nonce_url( trailingslashit( bp_get_group_permalink( groups_get_current_group() ) . 'admin/membership-requests/reject/' . $requests_template->request->user_id ), 'groups_reject_membership_request' ) );
    54415441        }
    54425442
    54435443/**
    function bp_group_request_accept_link() { 
    54615461                 *
    54625462                 * @param string $value URL to use to accept a membership request.
    54635463                 */
    5464                 return apply_filters( 'bp_get_group_request_accept_link', wp_nonce_url( trailingslashit( bp_get_group_permalink( groups_get_current_group() ) . 'admin/membership-requests/accept/' . $requests_template->request->membership_id ), 'groups_accept_membership_request' ) );
     5464                return apply_filters( 'bp_get_group_request_accept_link', wp_nonce_url( trailingslashit( bp_get_group_permalink( groups_get_current_group() ) . 'admin/membership-requests/accept/' . $requests_template->request->user_id ), 'groups_accept_membership_request' ) );
    54655465        }
    54665466
    54675467/**
  • src/bp-groups/classes/class-bp-group-member-query.php

    diff --git src/bp-groups/classes/class-bp-group-member-query.php src/bp-groups/classes/class-bp-group-member-query.php
    index d872810e3..859075921 100644
    class BP_Group_Member_Query extends BP_User_Query { 
    231231                $sql['orderby'] = "ORDER BY date_modified";
    232232                $sql['order']   = 'first_joined' === $this->query_vars['type'] ? 'ASC' : 'DESC';
    233233
    234                 $this->group_member_ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']}" );
     234                $group_member_ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']}" );
     235
     236                $invited_member_ids = array();
     237
     238                // If appropriate, fetch invitations and add them to the results.
     239                if ( ! $is_confirmed || ! is_null( $this->query_vars['invite_sent'] ) || ! is_null( $this->query_vars['inviter_id'] ) ) {
     240                        $invite_args = array(
     241                                'item_id' => $this->query_vars['group_id'],
     242                                'fields'  => 'user_ids',
     243                                'type'    => 'all',
     244                        );
     245
     246                        if ( ! is_null( $this->query_vars['invite_sent'] ) ) {
     247                                $invite_args['invite_sent'] = ! empty( $this->query_vars['invite_sent'] ) ? 'sent' : 'draft';
     248                        }
     249
     250                        // If inviter_id.
     251                        if ( ! is_null( $this->query_vars['inviter_id'] ) ) {
     252                                $inviter_id = $this->query_vars['inviter_id'];
     253
     254                                // Empty: inviter_id = 0. (pass false, 0, or empty array).
     255                                if ( empty( $inviter_id ) ) {
     256                                        $invite_args['type'] = 'request';
     257
     258                                /*
     259                                * The string 'any' matches any non-zero value (inviter_id != 0).
     260                                * These are invitations, not requests.
     261                                */
     262                                } elseif ( 'any' === $inviter_id ) {
     263                                        $invite_args['type'] = 'invite';
     264
     265                                // Assume that a list of inviter IDs has been passed.
     266                                } else {
     267                                        $invite_args['type'] = 'invite';
     268                                        // Parse and sanitize.
     269                                        $inviter_ids = wp_parse_id_list( $inviter_id );
     270                                        if ( ! empty( $inviter_ids ) ) {
     271                                                $invite_args['inviter_id'] = $inviter_ids;
     272                                        }
     273                                }
     274                        }
     275
     276                        /*
     277                         * If first_joined is the "type" of query, sort the oldest
     278                         * requests and invitations to the top.
     279                         */
     280                        if ( 'first_joined' === $this->query_vars['type'] ) {
     281                                $invite_args['order_by']   = 'date_modified';
     282                                $invite_args['sort_order'] = 'ASC';
     283                        }
     284
     285                        $invited_member_ids = groups_get_invites( $invite_args );
     286                }
     287
     288                $this->group_member_ids = array_merge( $group_member_ids, $invited_member_ids );
    235289
    236290                /**
    237291                 * Filters the member IDs for the current group member query.
    class BP_Group_Member_Query extends BP_User_Query { 
    330384                        }
    331385                }
    332386
     387                // Add accurate invitation info from the invitations table.
     388                $invites = groups_get_invites( array(
     389                        'user_id' => $user_ids_sql,
     390                        'item_id' => $this->query_vars['group_id'],
     391                        'type'    => 'all',
     392                ) );
     393                foreach ( $invites as $invite ) {
     394                        if ( isset( $this->results[ $invite->user_id ] ) ) {
     395                                $this->results[ $invite->user_id ]->comments      = $invite->content;
     396                                $this->results[ $invite->user_id ]->is_confirmed  = 0;
     397                                $this->results[ $invite->user_id ]->invitation_id = $invite->id;
     398                                $this->results[ $invite->user_id ]->invite_sent   = (int) $invite->invite_sent;
     399                                $this->results[ $invite->user_id ]->inviter_id    = $invite->inviter_id;
     400
     401                                // Backfill properties that are not being set above.
     402                                if ( ! isset( $this->results[ $invite->user_id ]->user_id ) ) {
     403                                        $this->results[ $invite->user_id ]->user_id = $invite->user_id;
     404                                }
     405                                if ( ! isset( $this->results[ $invite->user_id ]->is_admin ) ) {
     406                                        $this->results[ $invite->user_id ]->is_admin = 0;
     407                                }
     408                                if ( ! isset( $this->results[ $invite->user_id ]->is_mod ) ) {
     409                                        $this->results[ $invite->user_id ]->is_mod = 0;
     410                                }
     411                                if ( ! isset( $this->results[ $invite->user_id ]->is_banned ) ) {
     412                                        $this->results[ $invite->user_id ]->is_banned = 0;
     413                                }
     414                                if ( ! isset( $this->results[ $invite->user_id ]->date_modified ) ) {
     415                                        $this->results[ $invite->user_id ]->date_modified = $invite->date_modified;
     416                                }
     417                                if ( ! isset( $this->results[ $invite->user_id ]->user_title ) ) {
     418                                        $this->results[ $invite->user_id ]->user_title = '';
     419                                }
     420                                if ( ! isset( $this->results[ $invite->user_id ]->membership_id ) ) {
     421                                        $this->results[ $invite->user_id ]->membership_id = 0;
     422                                }
     423                        }
     424                }
     425
    333426                // Don't filter other BP_User_Query objects on the same page.
    334427                remove_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10 );
    335428        }
  • src/bp-groups/classes/class-bp-groups-group.php

    diff --git src/bp-groups/classes/class-bp-groups-group.php src/bp-groups/classes/class-bp-groups-group.php
    index 5c40c011b..218bd9b83 100644
    class BP_Groups_Group { 
    771771         *                  yet accepted.
    772772         */
    773773        public static function get_invites( $user_id, $group_id, $sent = null ) {
    774                 global $wpdb;
    775 
    776                 $bp  = buddypress();
    777                 $sql = $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE group_id = %d and is_confirmed = 0 AND inviter_id = %d", $group_id, $user_id );
    778 
    779                 // Query for a specific invite sent status.
    780                 if ( ! is_null( $sent ) ) {
    781                         $sql .= $wpdb->prepare( ' AND invite_sent = %d', $sent );
     774                if ( 0 === $sent ) {
     775                        $sent_arg = 'draft';
     776                } else if ( 1 === $sent ) {
     777                        $sent_arg = 'sent';
     778                } else {
     779                        $sent_arg = 'all';
    782780                }
    783781
    784                 return $wpdb->get_col( $sql );
     782                return groups_get_invites( array(
     783                        'item_id'     => $group_id,
     784                        'inviter_id'  => $user_id,
     785                        'invite_sent' => $sent_arg,
     786                        'fields'      => 'user_ids',
     787                ) );
    785788        }
    786789
    787790        /**
    class BP_Groups_Group { 
    959962         * }
    960963         */
    961964        public static function get_membership_requests( $group_id, $limit = null, $page = null ) {
    962                 global $wpdb;
    963 
    964                 if ( !empty( $limit ) && !empty( $page ) ) {
    965                         $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
     965                $args = array(
     966                        'item_id' => $group_id
     967                );
     968                if ( $limit ) {
     969                        $args['per_page'] = $limit;
    966970                }
     971                if ( $page ) {
     972                        $args['page'] = $page;
     973                }
    967974
    968                 $bp = buddypress();
    969 
    970                 $paged_requests = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0 AND inviter_id = 0{$pag_sql}", $group_id ) );
    971                 $total_requests = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0 AND inviter_id = 0", $group_id ) );
     975                $requests = groups_get_requests( $args );
     976                $total    = count( groups_get_membership_requested_user_ids( $group_id ) );
    972977
    973                 return array( 'requests' => $paged_requests, 'total' => $total_requests );
     978                return array( 'requests' => $requests, 'total' => $total );
    974979        }
    975980
    976981        /**
    class BP_Groups_Group { 
    16351640         *                  failure.
    16361641         */
    16371642        public static function delete_all_invites( $group_id ) {
    1638                 global $wpdb;
     1643                if ( empty( $group_id ) ) {
     1644                        return false;
     1645                }
    16391646
    1640                 $bp = buddypress();
     1647                $invites_class = new BP_Groups_Invitations();
    16411648
    1642                 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name_members} WHERE group_id = %d AND invite_sent = 1", $group_id ) );
     1649                return $invites_class->delete( array(
     1650                        'item_id' => $group_id,
     1651                ) );
    16431652        }
    16441653
    16451654        /**
  • new file src/bp-groups/classes/class-bp-groups-invitations.php

    diff --git src/bp-groups/classes/class-bp-groups-invitations.php src/bp-groups/classes/class-bp-groups-invitations.php
    new file mode 100644
    index 000000000..235feb2d3
    - +  
     1<?php
     2/**
     3 * Group invitations class.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 * @since 5.0.0
     8 */
     9
     10// Exit if accessed directly.
     11defined( 'ABSPATH' ) || exit;
     12
     13/**
     14 * Group invitations class.
     15 *
     16 * An extension of the core Invitations class that adapts the
     17 * core logic to accommodate group invitation behavior.
     18 *
     19 * @since 5.0.0
     20 */
     21class BP_Groups_Invitations extends BP_Invitations {
     22        /**
     23         * The name of the related component.
     24         *
     25         * @since 5.0.0
     26         * @access public
     27         * @var string
     28         */
     29        protected $component_name;
     30
     31        /**
     32         * Construct parameters.
     33         *
     34         * @since 3.1.0
     35         *
     36         * @param array|string $args {
     37
     38         * }
     39         */
     40        public function __construct( $args = '' ) {
     41                $this->component_name = buddypress()->groups->id;
     42                parent::__construct( array(
     43                        'component_name' => $this->component_name,
     44                ) );
     45        }
     46
     47        /**
     48         * This is where custom actions are added to run when notifications of an
     49         * invitation or request need to be generated & sent.
     50         *
     51         * @since 2.7.0
     52         *
     53         * @param int $id The ID of the invitation to mark as sent.
     54         * @return bool True on success, false on failure.
     55         */
     56        public function run_send_action( BP_Invitations_Invitation $invitation ) {
     57                // Notify group admins of the pending request
     58                if ( 'request' === $invitation->type ) {
     59                        $admins = groups_get_group_admins( $invitation->item_id );
     60
     61                        foreach ( $admins as $admin ) {
     62                                groups_notification_new_membership_request( $invitation->user_id, $admin->user_id, $invitation->item_id, $invitation->id );
     63                        }
     64                        return true;
     65
     66                // Notify the invitee of the invitation.
     67                } else {
     68                        $group = groups_get_group( $invitation->item_id );
     69                        groups_notification_group_invites( $group, $invitation->user_id, $invitation->inviter_id );
     70                        return true;
     71                }
     72        }
     73
     74        /**
     75         * This is where custom actions are added to run when an invitation
     76         * or request is accepted.
     77         *
     78         * @since 2.7.0
     79         *
     80         * @param int $id The ID of the invitation to mark as sent.
     81         * @return bool True on success, false on failure.
     82         */
     83        public function run_acceptance_action( $type = 'invite', $r  ) {
     84                // If the user is already a member (because BP at one point allowed two invitations to
     85                // slip through), return early.
     86                if ( groups_is_user_member( $r['user_id'], $r['item_id'] ) ) {
     87                        return true;
     88                }
     89
     90                // Create the new membership
     91                $member = new BP_Groups_Member( $r['user_id'], $r['item_id'] );
     92
     93                if ( 'request' === $type ) {
     94                        $member->accept_request();
     95                } else {
     96                        $member->accept_invite();
     97                }
     98
     99                if ( ! $member->save() ) {
     100                        return false;
     101                }
     102
     103                // Modify group meta.
     104                groups_update_groupmeta( $r['item_id'], 'last_activity', bp_core_current_time() );
     105
     106                return true;
     107        }
     108
     109        /**
     110         * With group invitations, we don't need to keep the old record, so we delete rather than
     111         * mark invitations as "accepted."
     112         *
     113         * @since 2.7.0
     114         *
     115         * @see BP_Invitations_Invitation::mark_accepted_by_data()
     116         *      for a description of arguments.
     117         */
     118        public function mark_accepted( $args ) {
     119                // Delete all existing invitations/requests to this group for this user.
     120                $this->delete( array(
     121                        'user_id' => $args['user_id'],
     122                        'item_id' => $args['item_id'],
     123                        'type'    => 'all'
     124                ) );
     125        }
     126
     127        /**
     128         * Should this invitation be created?
     129         *
     130         * @since 5.0.0
     131         */
     132        public function allow_invitation( $args ) {
     133                // Does the inviter have this capability?
     134                if ( ! bp_user_can( $args['inviter_id'], 'groups_send_invitation', array( 'group_id' => $args['item_id'] ) ) ) {
     135                        return false;
     136                }
     137
     138                // Is the invited user eligible to receive an invitation?
     139                if ( ! bp_user_can( $args['user_id'], 'groups_receive_invitation', array( 'group_id' => $args['item_id'] ) ) ) {
     140                        return false;
     141                }
     142
     143                // Prevent duplicated invitations.
     144                if ( groups_check_has_invite_from_user( $args['user_id'], $args['item_id'], $args['inviter_id'], 'all' ) ) {
     145                        return false;
     146                }
     147
     148                return true;
     149        }
     150
     151        /**
     152         * Should this request be created?
     153         *
     154         * @since 5.0.0
     155         */
     156        public function allow_request( $args ) {
     157                // Does the requester have this capability? (Also checks for duplicates.)
     158                if ( ! bp_user_can( $args['user_id'], 'groups_request_membership', array( 'group_id' => $args['item_id'] ) ) ) {
     159                        return false;
     160                }
     161
     162                return true;
     163        }
     164}
  • src/bp-groups/classes/class-bp-groups-member.php

    diff --git src/bp-groups/classes/class-bp-groups-member.php src/bp-groups/classes/class-bp-groups-member.php
    index 66f833022..dc54b9466 100644
    class BP_Groups_Member { 
    767767        }
    768768
    769769        /**
    770          * Get a user's outstanding group invitations.
     770         * Get group objects for groups that a user is currently invited to.
    771771         *
    772772         * @since 1.6.0
    773773         *
    class BP_Groups_Member { 
    784784         * }
    785785         */
    786786        public static function get_invites( $user_id, $limit = false, $page = false, $exclude = false ) {
    787                 global $wpdb;
    788 
    789                 $pag_sql = ( !empty( $limit ) && !empty( $page ) ) ? $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) ) : '';
    790 
    791                 if ( !empty( $exclude ) ) {
    792                         $exclude     = implode( ',', wp_parse_id_list( $exclude ) );
    793                         $exclude_sql = " AND g.id NOT IN ({$exclude})";
    794                 } else {
    795                         $exclude_sql = '';
    796                 }
    797 
    798                 $bp = buddypress();
    799 
    800                 $paged_groups = $wpdb->get_results( $wpdb->prepare( "SELECT g.*, gm1.meta_value as total_member_count, gm2.meta_value as last_activity FROM {$bp->groups->table_name_groupmeta} gm1, {$bp->groups->table_name_groupmeta} gm2, {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE g.id = m.group_id AND g.id = gm1.group_id AND g.id = gm2.group_id AND gm2.meta_key = 'last_activity' AND gm1.meta_key = 'total_member_count' AND m.is_confirmed = 0 AND m.inviter_id != 0 AND m.invite_sent = 1 AND m.user_id = %d {$exclude_sql} ORDER BY m.date_modified ASC {$pag_sql}", $user_id ) );
    801 
    802                 return array( 'groups' => $paged_groups, 'total' => self::get_invite_count_for_user( $user_id ) );
     787                return groups_get_invites_for_user( $user_id, $limit, $page, $exclude );
    803788        }
    804789
    805790        /**
    class BP_Groups_Member { 
    811796         * @return int
    812797         */
    813798        public static function get_invite_count_for_user( $user_id = 0 ) {
    814                 global $wpdb;
    815 
    816                 $bp = buddypress();
    817 
    818                 $count = wp_cache_get( $user_id, 'bp_group_invite_count' );
    819 
    820                 if ( false === $count ) {
    821                         $count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT m.group_id) FROM {$bp->groups->table_name_members} m, {$bp->groups->table_name} g WHERE m.group_id = g.id AND m.is_confirmed = 0 AND m.inviter_id != 0 AND m.invite_sent = 1 AND m.user_id = %d", $user_id ) );
    822                         wp_cache_set( $user_id, $count, 'bp_group_invite_count' );
    823                 }
    824 
    825                 return $count;
     799                return groups_get_invite_count_for_user( $user_id );
    826800        }
    827801
    828802        /**
    class BP_Groups_Member { 
    859833                        'where'  => '',
    860834                        'limits' => '',
    861835                );
    862 
     836//@TODO 6210.
    863837                switch ( $r['type'] ) {
    864                         case 'pending_request' :
    865                                 $sql['where'] = $wpdb->prepare( "user_id = %d AND is_confirmed = 0 AND inviter_id = 0", $user_id );
    866                         break;
    867 
    868                         case 'pending_received_invitation' :
    869                                 $sql['where'] = $wpdb->prepare( "user_id = %d AND is_confirmed = 0 AND inviter_id != 0", $user_id );
    870                         break;
    871 
    872                         case 'pending_sent_invitation' :
    873                                 $sql['where'] = $wpdb->prepare( "inviter_id = %d AND is_confirmed = 0", $user_id );
    874                         break;
    875 
    876838                        case 'membership' :
    877839                        default :
    878840                                $sql['where'] = $wpdb->prepare( "user_id = %d AND is_confirmed = 1", $user_id );
    class BP_Groups_Member { 
    912874         * @return int|null The ID of the invitation if found; null if not found.
    913875         */
    914876        public static function check_has_invite( $user_id, $group_id, $type = 'sent' ) {
    915                 global $wpdb;
    916 
    917                 if ( empty( $user_id ) )
    918                         return false;
    919 
    920                 $bp  = buddypress();
    921                 $sql = "SELECT id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id = %d AND is_confirmed = 0 AND inviter_id != 0";
    922 
    923                 if ( 'sent' == $type )
    924                         $sql .= " AND invite_sent = 1";
    925 
    926                 $query = $wpdb->get_var( $wpdb->prepare( $sql, $user_id, $group_id ) );
    927 
    928                 return is_numeric( $query ) ? (int) $query : $query;
     877                return groups_is_user_invited( $user_id, $group_id, $type );
    929878        }
    930879
    931880        /**
    class BP_Groups_Member { 
    937886         *
    938887         * @param  int $user_id  ID of the user.
    939888         * @param  int $group_id ID of the group.
     889         * @param  int $inviter_id ID of the inviter. Specify if you want to delete
     890         *                         a specific invite. Leave false if you want to
     891         *                         delete all invites to this group.
    940892         * @return int Number of records deleted.
    941893         */
    942         public static function delete_invite( $user_id, $group_id ) {
    943                 global $wpdb;
    944 
    945                 if ( empty( $user_id ) ) {
    946                         return false;
    947                 }
    948 
     894        public static function delete_invite( $user_id, $group_id, $inviter_id = false ) {
    949895                /**
    950896                 * Fires before a group invitation is deleted.
    951897                 *
    952898                 * @since 2.6.0
     899                 * @since 5.0.0 Added $inviter_id
    953900                 *
    954901                 * @param int $user_id  ID of the user.
    955902                 * @param int $group_id ID of the group.
     903                 * @param  int $inviter_id ID of the inviter.
    956904                 */
    957                 do_action( 'bp_groups_member_before_delete_invite', $user_id, $group_id );
    958 
    959                 $table_name = buddypress()->groups->table_name_members;
    960 
    961                 $sql = "DELETE FROM {$table_name}
    962                                 WHERE user_id = %d
    963                                         AND group_id = %d
    964                                         AND is_confirmed = 0
    965                                         AND inviter_id != 0";
    966 
    967                 $prepared = $wpdb->prepare( $sql, $user_id, $group_id );
     905                do_action( 'bp_groups_member_before_delete_invite', $user_id, $group_id, $inviter_id );
    968906
    969                 return $wpdb->query( $prepared );
     907                return groups_delete_invite( $user_id, $group_id, $inviter_id );
    970908        }
    971909
    972910        /**
    class BP_Groups_Member { 
    979917         * @return int Number of records deleted.
    980918         */
    981919        public static function delete_request( $user_id, $group_id ) {
    982                 global $wpdb;
    983 
    984                 if ( empty( $user_id ) )
    985                         return false;
    986 
    987                 $bp = buddypress();
    988 
    989                 return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id = %d AND is_confirmed = 0 AND inviter_id = 0 AND invite_sent = 0", $user_id, $group_id ) );
     920                return groups_delete_membership_request( false, $user_id, $group_id );
    990921        }
    991922
    992923        /**
    class BP_Groups_Member { 
    11041035         * @return int Database ID of the membership if found; int 0 on failure.
    11051036         */
    11061037        public static function check_for_membership_request( $user_id, $group_id ) {
    1107                 global $wpdb;
    1108 
    1109                 if ( empty( $user_id ) )
    1110                         return false;
    1111 
    1112                 $bp = buddypress();
    1113 
    1114                 return $wpdb->query( $wpdb->prepare( "SELECT id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id = %d AND is_confirmed = 0 AND is_banned = 0 AND inviter_id = 0", $user_id, $group_id ) );
     1038                return groups_is_user_pending( $user_id, $group_id );
    11151039        }
    11161040
    11171041        /**
    class BP_Groups_Member { 
    12921216         * @return array IDs of users with outstanding membership requests.
    12931217         */
    12941218        public static function get_all_membership_request_user_ids( $group_id ) {
    1295                 global $wpdb;
    1296 
    1297                 $bp = buddypress();
    1298 
    1299                 return array_map( 'intval', $wpdb->get_col( $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0 AND inviter_id = 0", $group_id ) ) );
     1219                return groups_get_membership_requested_user_ids( $group_id );
    13001220        }
    13011221
    13021222        /**
  • src/bp-groups/screens/single/admin/membership-requests.php

    diff --git src/bp-groups/screens/single/admin/membership-requests.php src/bp-groups/screens/single/admin/membership-requests.php
    index ca12c2cc0..cace86eb0 100644
    function groups_screen_group_admin_requests() { 
    2424        }
    2525
    2626        $request_action = (string) bp_action_variable( 1 );
    27         $membership_id  = (int) bp_action_variable( 2 );
     27        $user_id        = (int) bp_action_variable( 2 );
     28        $group_id       = bp_get_current_group_id();
    2829
    29         if ( !empty( $request_action ) && !empty( $membership_id ) ) {
    30                 if ( 'accept' == $request_action && is_numeric( $membership_id ) ) {
     30        if ( ! empty( $request_action ) && ! empty( $user ) ) {
     31                if ( 'accept' == $request_action && is_numeric( $user_id) ) {
    3132
    3233                        // Check the nonce first.
    33                         if ( !check_admin_referer( 'groups_accept_membership_request' ) )
     34                        if ( ! check_admin_referer( 'groups_accept_membership_request' ) ) {
    3435                                return false;
     36                        }
    3537
    3638                        // Accept the membership request.
    37                         if ( !groups_accept_membership_request( $membership_id ) )
     39                        if ( ! groups_accept_membership_request( false, $user_id, $group_id ) ) {
    3840                                bp_core_add_message( __( 'There was an error accepting the membership request. Please try again.', 'buddypress' ), 'error' );
    39                         else
     41                        } else {
    4042                                bp_core_add_message( __( 'Group membership request accepted', 'buddypress' ) );
     43                        }
    4144
    42                 } elseif ( 'reject' == $request_action && is_numeric( $membership_id ) ) {
     45                } elseif ( 'reject' == $request_action && is_numeric( $user_id ) ) {
    4346                        /* Check the nonce first. */
    44                         if ( !check_admin_referer( 'groups_reject_membership_request' ) )
     47                        if ( ! check_admin_referer( 'groups_reject_membership_request' ) ) {
    4548                                return false;
     49                        }
    4650
    4751                        // Reject the membership request.
    48                         if ( !groups_reject_membership_request( $membership_id ) )
     52                        if ( ! groups_reject_membership_request( false, $user_id, $group_id ) ) {
    4953                                bp_core_add_message( __( 'There was an error rejecting the membership request. Please try again.', 'buddypress' ), 'error' );
    50                         else
     54                        } else {
    5155                                bp_core_add_message( __( 'Group membership request rejected', 'buddypress' ) );
     56                        }
    5257                }
    5358
     59                // Was the member added to the group?
     60                $membership_id = groups_is_user_member( $user_id, $group_id );
     61
    5462                /**
    5563                 * Fires before the redirect if a group membership request has been handled.
    5664                 *
    function groups_screen_group_admin_requests() { 
    5866                 *
    5967                 * @param int    $id             ID of the group that was edited.
    6068                 * @param string $request_action Membership request action being performed.
    61                  * @param int    $membership_id  The key of the action_variables array that you want.
     69                 * @param int    $membership_id  The membership ID of the new user; false if rejected.
     70                 * @param int    $user_id        The ID of the requesting user.
     71                 * @param int    $group_id       The ID of the requested group.
    6272                 */
    63                 do_action( 'groups_group_request_managed', $bp->groups->current_group->id, $request_action, $membership_id );
     73                do_action( 'groups_group_request_managed', $bp->groups->current_group->id, $request_action, $membership_id, $user_id, $group_id );
    6474                bp_core_redirect( bp_get_group_permalink( groups_get_current_group() ) . 'admin/membership-requests/' );
    6575        }
    6676
    function groups_screen_group_admin_requests() { 
    8292         */
    8393        bp_core_load_template( apply_filters( 'groups_template_group_admin_requests', 'groups/single/home' ) );
    8494}
    85 add_action( 'bp_screens', 'groups_screen_group_admin_requests' );
    86  No newline at end of file
     95add_action( 'bp_screens', 'groups_screen_group_admin_requests' );
  • src/class-buddypress.php

    diff --git src/class-buddypress.php src/class-buddypress.php
    index 21bfd2224..0cfbaff4d 100644
    class BuddyPress { 
    487487                require( $this->plugin_dir . 'bp-core/bp-core-moderation.php'       );
    488488                require( $this->plugin_dir . 'bp-core/bp-core-loader.php'           );
    489489                require( $this->plugin_dir . 'bp-core/bp-core-customizer-email.php' );
     490                require( $this->plugin_dir . 'bp-core/bp-core-invitations-cache.php' );
    490491
    491492                // Maybe load deprecated functionality (this double negative is proof positive!)
    492493                if ( ! bp_get_option( '_bp_ignore_deprecated_code', ! $this->load_deprecated ) ) {
    class BuddyPress { 
    568569                        'BP_Walker_Category_Checklist' => 'core',
    569570                        'BP_Walker_Nav_Menu_Checklist' => 'core',
    570571                        'BP_Walker_Nav_Menu'           => 'core',
     572                        'BP_Invitations'               => 'core',
     573                        'BP_Invitations_Invitation'    => 'core',
    571574
    572575                        'BP_Core_Friends_Widget' => 'friends',
    573576
  • new file tests/phpunit/testcases/core/invitations.php

    diff --git tests/phpunit/testcases/core/invitations.php tests/phpunit/testcases/core/invitations.php
    new file mode 100644
    index 000000000..d41d32856
    - +  
     1<?php
     2/**
     3 * @group core
     4 * @group invitations
     5 */
     6 class BP_Tests_Invitations extends BP_UnitTestCase {
     7                public function test_bp_invitations_add_invitation_vanilla() {
     8                $old_current_user = get_current_user_id();
     9
     10                $u1 = $this->factory->user->create();
     11                $u2 = $this->factory->user->create();
     12                $u3 = $this->factory->user->create();
     13                $this->set_current_user( $u1 );
     14
     15                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     16
     17                // Create a couple of invitations.
     18                $invite_args = array(
     19                        'user_id'           => $u3,
     20                        'inviter_id'            => $u1,
     21                        'component_action'  => 'cupcakes',
     22                        'item_id'           => 1,
     23                        'send_invite'       => 'sent',
     24                );
     25                $i1 = $invites_class->add_invitation( $invite_args );
     26                $invite_args['inviter_id'] = $u2;
     27                $i2 = $invites_class->add_invitation( $invite_args );
     28
     29                $get_invites = array(
     30                        'user_id'        => $u3,
     31                        'fields'         => 'ids',
     32                );
     33                $invites = $invites_class->get_invitations( $get_invites );
     34                $this->assertEqualSets( array( $i1, $i2 ), $invites );
     35
     36                $this->set_current_user( $old_current_user );
     37        }
     38
     39        public function test_bp_invitations_add_invitation_avoid_duplicates() {
     40                $old_current_user = get_current_user_id();
     41
     42                $u1 = $this->factory->user->create();
     43                $u2 = $this->factory->user->create();
     44                $this->set_current_user( $u1 );
     45
     46                $invites_class = new BP_Invitations( array( 'component_name' => 'blogs' ) );
     47
     48                // Create an invitation.
     49                $invite_args = array(
     50                        'user_id'           => $u2,
     51                        'inviter_id'            => $u1,
     52                        'component_action'  => 'blog_invite',
     53                        'item_id'           => 1,
     54                        'send_invite'       => 'sent',
     55                );
     56                $i1 = $invites_class->add_invitation( $invite_args );
     57                // Attempt to create a duplicate.
     58                $this->assertFalse( $invites_class->add_invitation( $invite_args ) );
     59
     60                $this->set_current_user( $old_current_user );
     61        }
     62
     63        public function test_bp_invitations_add_invitation_invite_plus_request_should_accept() {
     64                $old_current_user = get_current_user_id();
     65
     66                $u1 = $this->factory->user->create();
     67                $u2 = $this->factory->user->create();
     68                $u3 = $this->factory->user->create();
     69                $this->set_current_user( $u1 );
     70
     71                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     72
     73                // Create an invitation.
     74                $invite_args = array(
     75                        'user_id'           => $u3,
     76                        'inviter_id'            => $u1,
     77                        'component_action'  => 'cupcakes',
     78                        'item_id'           => 1,
     79                        'send_invite'       => 'sent',
     80                );
     81                $i1 = $invites_class->add_invitation( $invite_args );
     82
     83                // Create a request.
     84                $request_args = array(
     85                        'user_id'           => $u3,
     86                        'component_action'  => 'cupcakes',
     87                        'item_id'           => 1,
     88                );
     89                $r1 = $invites_class->add_request( $request_args );
     90
     91                $get_invites = array(
     92                        'user_id'          => $u3,
     93                        'component_action' => 'cupcakes',
     94                        'accepted'         => 'accepted'
     95                );
     96                $invites = $invites_class->get_invitations( $get_invites );
     97                $this->assertEqualSets( array( $i1 ), wp_list_pluck( $invites, 'id' ) );
     98
     99                $this->set_current_user( $old_current_user );
     100        }
     101
     102        public function test_bp_invitations_add_invitation_unsent_invite_plus_request_should_not_accept() {
     103                $old_current_user = get_current_user_id();
     104
     105                $u1 = $this->factory->user->create();
     106                $u2 = $this->factory->user->create();
     107                $u3 = $this->factory->user->create();
     108                $this->set_current_user( $u1 );
     109
     110                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     111
     112                // Create an invitation.
     113                $invite_args = array(
     114                        'user_id'           => $u3,
     115                        'inviter_id'            => $u1,
     116                        'component_action'  => 'cupcakes',
     117                        'item_id'           => 1,
     118                        'send_invite'       => 0,
     119                );
     120                $i1 = $invites_class->add_invitation( $invite_args );
     121
     122                // Create a request.
     123                $request_args = array(
     124                        'user_id'           => $u3,
     125                        'component_action'  => 'cupcakes',
     126                        'item_id'           => 1,
     127                );
     128                $r1 = $invites_class->add_request( $request_args );
     129
     130                $get_invites = array(
     131                        'user_id'          => $u3,
     132                        'component_action' => 'cupcakes',
     133                        'accepted'         => 'accepted'
     134                );
     135                $invites = $invites_class->get_invitations( $get_invites );
     136                $this->assertEqualSets( array(), wp_list_pluck( $invites, 'id' ) );
     137
     138                $this->set_current_user( $old_current_user );
     139        }
     140
     141        public function test_bp_invitations_add_invitation_unsent_invite_plus_request_then_send_invite_should_accept() {
     142                $old_current_user = get_current_user_id();
     143
     144                $u1 = $this->factory->user->create();
     145                $u2 = $this->factory->user->create();
     146                $u3 = $this->factory->user->create();
     147                $this->set_current_user( $u1 );
     148
     149                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     150
     151                // Create an invitation.
     152                $invite_args = array(
     153                        'user_id'           => $u3,
     154                        'inviter_id'            => $u1,
     155                        'component_action'  => 'cupcakes',
     156                        'item_id'           => 1,
     157                        'send_invite'       => 0,
     158                );
     159                $i1 = $invites_class->add_invitation( $invite_args );
     160
     161                // Create a request.
     162                $request_args = array(
     163                        'user_id'           => $u3,
     164                        'component_action'  => 'cupcakes',
     165                        'item_id'           => 1,
     166                );
     167                $r1 = $invites_class->add_request( $request_args );
     168
     169                $invites_class->send_invitation_by_id( $i1 );
     170
     171                // Check that both the request and invitation are marked 'accepted'.
     172                $get_invites = array(
     173                        'user_id'          => $u3,
     174                        'component_action' => 'cupcakes',
     175                        'type'             => 'all',
     176                        'accepted'         => 'accepted',
     177                        'fields'           => 'ids'
     178                );
     179                $invites = $invites_class->get_invitations( $get_invites );
     180                $this->assertEqualSets( array( $i1, $r1 ), $invites );
     181
     182                $this->set_current_user( $old_current_user );
     183        }
     184
     185        public function test_bp_invitations_add_request_vanilla() {
     186                $old_current_user = get_current_user_id();
     187
     188                $u1 = $this->factory->user->create();
     189                $this->set_current_user( $u1 );
     190
     191                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     192
     193                // Create a couple of requests.
     194                $request_args = array(
     195                        'user_id'           => $u1,
     196                        'component_action'  => 'cupcakes',
     197                        'item_id'           => 7,
     198                );
     199                $r1 = $invites_class->add_request( $request_args );
     200                $request_args['item_id'] = 4;
     201                $r2 = $invites_class->add_request( $request_args );
     202
     203                $get_requests = array(
     204                        'user_id'           => $u1,
     205                        'component_action'  => 'cupcakes',
     206                        'fields'            => 'ids'
     207                );
     208                $requests = $invites_class->get_requests( $get_requests );
     209                $this->assertEqualSets( array( $r1, $r2 ), $requests );
     210
     211                $this->set_current_user( $old_current_user );
     212        }
     213
     214        public function test_bp_invitations_add_request_avoid_duplicates() {
     215                $old_current_user = get_current_user_id();
     216
     217                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     218
     219                $u1 = $this->factory->user->create();
     220                $this->set_current_user( $u1 );
     221
     222                // Create a couple of requests.
     223                $request_args = array(
     224                        'user_id'           => $u1,
     225                        'component_action'  => 'cupcakes',
     226                        'item_id'           => 7,
     227                );
     228                $r1 = $invites_class->add_request( $request_args );
     229                // Attempt to create a duplicate.
     230                $this->assertFalse( $invites_class->add_request( $request_args ) );
     231
     232                $this->set_current_user( $old_current_user );
     233        }
     234
     235        public function test_bp_invitations_add_request_request_plus_sent_invite_should_accept() {
     236                $old_current_user = get_current_user_id();
     237
     238                $u1 = $this->factory->user->create();
     239                $u2 = $this->factory->user->create();
     240                $this->set_current_user( $u1 );
     241
     242                $invites_class = new BP_Invitations( array( 'component_name' => 'cakes' ) );
     243
     244                // Create a request.
     245                $request_args = array(
     246                        'user_id'           => $u2,
     247                        'component_action'  => 'cupcakes',
     248                        'item_id'           => 1,
     249                );
     250                $r1 = $invites_class->add_request( $request_args );
     251
     252                // Create an invitation.
     253                $invite_args = array(
     254                        'user_id'           => $u2,
     255                        'inviter_id'            => $u1,
     256                        'component_action'  => 'cupcakes',
     257                        'item_id'           => 1,
     258                        'send_invite'       => 1,
     259                );
     260                $i1 = $invites_class->add_invitation( $invite_args );
     261
     262                // Check that both the request and invitation are marked 'accepted'.
     263                $get_invites = array(
     264                        'user_id'          => $u2,
     265                        'type'             => 'all',
     266                        'component_action' => 'cupcakes',
     267                        'accepted'         => 'accepted',
     268                        'fields'           => 'ids'
     269                );
     270                $invites = $invites_class->get_invitations( $get_invites );
     271                $this->assertEqualSets( array( $r1, $i1 ), $invites );
     272
     273                $this->set_current_user( $old_current_user );
     274        }
     275
     276}
  • tests/phpunit/testcases/groups/class-bp-groups-group.php

    diff --git tests/phpunit/testcases/groups/class-bp-groups-group.php tests/phpunit/testcases/groups/class-bp-groups-group.php
    index a76d4e72c..f03a4c801 100644
    class BP_Tests_BP_Groups_Group_TestCases extends BP_UnitTestCase { 
    13721372         */
    13731373        public function test_get_group_extras_invited() {
    13741374                $u = self::factory()->user->create();
    1375                 $g = self::factory()->group->create();
     1375                $u2 = self::factory()->user->create();
     1376                $g = self::factory()->group->create( array( 'creator_id' => $u2, 'status' => 'private' ) );
    13761377
    1377                 $invite                = new BP_Groups_Member;
    1378                 $invite->group_id      = $g;
    1379                 $invite->user_id       = $u;
    1380                 $invite->date_modified = bp_core_current_time();
    1381                 $invite->invite_sent   = true;
    1382                 $invite->is_confirmed  = false;
    1383                 $invite->save();
     1378                // Outstanding invitations should be left intact.
     1379                groups_invite_user( array(
     1380                        'user_id' => $u,
     1381                        'group_id' => $g,
     1382                        'inviter_id' => $u2,
     1383                        'send_invite' => 1,
     1384                ) );
    13841385
    13851386                $paged_groups = array();
    13861387                $paged_groups[] = new stdClass;
    class BP_Tests_BP_Groups_Group_TestCases extends BP_UnitTestCase { 
    14111412         */
    14121413        public function test_get_group_extras_pending() {
    14131414                $u = self::factory()->user->create();
    1414                 $g = self::factory()->group->create();
     1415                $g = self::factory()->group->create( array( 'status' => 'private' ) );
    14151416
    1416                 $invite                = new BP_Groups_Member;
    1417                 $invite->group_id      = $g;
    1418                 $invite->user_id       = $u;
    1419                 $invite->date_modified = bp_core_current_time();
    1420                 $invite->invite_sent   = false;
    1421                 $invite->is_confirmed  = false;
    1422                 $invite->save();
     1417                // Create membership request
     1418                groups_send_membership_request( array(
     1419                        'user_id'       => $u,
     1420                        'group_id'      => $g,
     1421                ) );
    14231422
    14241423                $paged_groups = array();
    14251424                $paged_groups[] = new stdClass;
  • tests/phpunit/testcases/groups/class-bp-groups-member.php

    diff --git tests/phpunit/testcases/groups/class-bp-groups-member.php tests/phpunit/testcases/groups/class-bp-groups-member.php
    index b052f81fe..480c2ae0f 100644
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    2020                array_map( 'groups_delete_group', self::$group_ids );
    2121        }
    2222
    23         public static function invite_user_to_group( $user_id, $group_id, $inviter_id ) {
    24                 $invite                = new BP_Groups_Member;
    25                 $invite->group_id      = $group_id;
    26                 $invite->user_id       = $user_id;
    27                 $invite->date_modified = bp_core_current_time();
    28                 $invite->inviter_id    = $inviter_id;
    29                 $invite->is_confirmed  = 0;
    30                 $invite->invite_sent   = 1;
    31 
    32                 $invite->save();
    33                 return $invite->id;
    34         }
    35 
    36         public static function create_group_membership_request( $user_id, $group_id ) {
    37                 $request                = new BP_Groups_Member;
    38                 $request->group_id      = $group_id;
    39                 $request->user_id       = $user_id;
    40                 $request->date_modified = bp_core_current_time();
    41                 $request->inviter_id    = 0;
    42                 $request->is_confirmed  = 0;
    43 
    44                 $request->save();
    45                 return $request->id;
    46         }
    47 
    4823        public function test_get_recently_joined_with_filter() {
    4924                $g1 = self::factory()->group->create( array(
    5025                        'name' => 'Tab',
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    133108        }
    134109
    135110        public function test_get_invites_with_exclude() {
     111                $u1 = self::factory()->user->create();
     112                $u2 = self::factory()->user->create();
    136113                $g1 = self::factory()->group->create( array(
    137                         'name' => 'RC Cola',
     114                        'status' => 'private',
     115                        'creator_id' => $u1
    138116                ) );
    139117                $g2 = self::factory()->group->create( array(
    140                         'name' => 'Pepsi',
     118                        'status' => 'private',
     119                        'creator_id' => $u1
    141120                ) );
    142121
    143                 $u1 = self::factory()->user->create();
    144                 $u2 = self::factory()->user->create();
    145                 self::add_user_to_group( $u1, $g1 );
    146                 self::add_user_to_group( $u1, $g2 );
    147                 self::invite_user_to_group( $u2, $g1, $u1 );
    148                 self::invite_user_to_group( $u2, $g2, $u1 );
     122                groups_invite_user( array(
     123                        'user_id' => $u2,
     124                        'group_id' => $g1,
     125                        'inviter_id' => $u1,
     126                        'send_invite' => 1,
     127                ) );
     128                groups_invite_user( array(
     129                        'user_id' => $u2,
     130                        'group_id' => $g2,
     131                        'inviter_id' => $u1,
     132                        'send_invite' => 1,
     133                ) );
    149134
    150135                $groups = BP_Groups_Member::get_invites( $u2, false, false, array( 'awesome', $g1 ) );
    151136
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    282267                ) );
    283268
    284269                // Membership requests should be removed.
    285                 self::create_group_membership_request( $u1, $g );
     270                groups_send_membership_request( array(
     271                        'user_id' => $u1,
     272                        'group_id' => $g
     273                ) );
     274
    286275                groups_reject_membership_request( null, $u1, $g );
    287276                $u1_has_request = groups_check_for_membership_request( $u1, $g );
    288277                $this->assertEquals( 0, $u1_has_request );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    325314                ) );
    326315
    327316                // Outstanding invitations should be left intact.
    328                 self::invite_user_to_group( $u2, $g, $u1 );
     317                groups_invite_user( array(
     318                        'user_id' => $u2,
     319                        'group_id' => $g,
     320                        'inviter_id' => $u1,
     321                        'send_invite' => 1,
     322                ) );
    329323                groups_reject_membership_request( null, $u2, $g );
    330324                $u2_has_invite = groups_check_user_has_invite( $u2, $g );
    331325                $this->assertTrue( is_numeric( $u2_has_invite ) && $u2_has_invite > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    343337                ) );
    344338
    345339                // Membership requests should be removed.
    346                 self::create_group_membership_request( $u1, $g );
     340                groups_send_membership_request( array(
     341                        'user_id' => $u1,
     342                        'group_id' => $g
     343                ) );
    347344                groups_delete_membership_request( null, $u1, $g );
    348345                $u1_has_request = groups_check_for_membership_request( $u1, $g );
    349346                $this->assertEquals( 0, $u1_has_request );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    386383                ) );
    387384
    388385                // Outstanding invitations should be left intact.
    389                 self::invite_user_to_group( $u2, $g, $u1 );
     386                groups_invite_user( array(
     387                        'user_id' => $u2,
     388                        'group_id' => $g,
     389                        'inviter_id' => $u1,
     390                        'send_invite' => 1,
     391                ) );
     392
    390393                groups_delete_membership_request( null, $u2, $g );
    391394                $u2_has_invite = groups_check_user_has_invite( $u2, $g );
    392395                $this->assertTrue( is_numeric( $u2_has_invite ) && $u2_has_invite > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    410413                ) );
    411414
    412415                // The invitation should be removed.
    413                 self::invite_user_to_group( $u2, $g, $u1 );
     416                groups_invite_user( array(
     417                        'user_id' => $u2,
     418                        'group_id' => $g,
     419                        'inviter_id' => $u1,
     420                        'send_invite' => 1,
     421                ) );
     422
    414423                groups_reject_invite( $u2, $g );
    415424                $u2_has_invite = groups_check_user_has_invite( $u2, $g, 'all' );
    416425                $this->assertEquals( 0, $u2_has_invite );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    450459                ) );
    451460
    452461                // Membership requests should be left intact.
    453                 self::create_group_membership_request( $u1, $g );
     462                groups_send_membership_request( array(
     463                        'user_id' => $u1,
     464                        'group_id' => $g
     465                ) );
    454466                groups_reject_invite( $u1, $g );
    455467                $u1_has_request = groups_check_for_membership_request( $u1, $g );
    456468                $this->assertTrue( is_numeric( $u1_has_request ) && $u1_has_request > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    474486                ) );
    475487
    476488                // The invitation should be removed.
    477                 self::invite_user_to_group( $u2, $g, $u1 );
     489                groups_invite_user( array(
     490                        'user_id' => $u2,
     491                        'group_id' => $g,
     492                        'inviter_id' => $u1,
     493                        'send_invite' => 1,
     494                ) );
     495
    478496                groups_delete_invite( $u2, $g );
    479497                $u2_has_invite = groups_check_user_has_invite( $u2, $g, 'all' );
    480498                $this->assertEquals( 0, $u2_has_invite );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    547565                ) );
    548566
    549567                // Membership requests should be left intact.
    550                 self::create_group_membership_request( $u1, $g );
     568                groups_send_membership_request( array(
     569                        'user_id' => $u1,
     570                        'group_id' => $g
     571                ) );
    551572                groups_delete_invite( $u1, $g );
    552573                $u1_has_request = groups_check_for_membership_request( $u1, $g );
    553574                $this->assertTrue( is_numeric( $u1_has_request ) && $u1_has_request > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    571592                ) );
    572593
    573594                // The invitation should be removed.
    574                 self::invite_user_to_group( $u2, $g, $u1 );
     595                groups_invite_user( array(
     596                        'user_id' => $u2,
     597                        'group_id' => $g,
     598                        'inviter_id' => $u1,
     599                        'send_invite' => 1,
     600                ) );
    575601                groups_uninvite_user( $u2, $g );
    576602                $u2_has_invite = groups_check_user_has_invite( $u2, $g, 'all' );
    577603                $this->assertEquals( 0, $u2_has_invite );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    612638                ) );
    613639
    614640                // Membership requests should be left intact.
    615                 self::create_group_membership_request( $u1, $g );
     641                groups_send_membership_request( array(
     642                        'user_id' => $u1,
     643                        'group_id' => $g
     644                ) );
    616645                groups_uninvite_user( $u1, $g );
    617646                $u1_has_request = groups_check_for_membership_request( $u1, $g );
    618647                $this->assertTrue( is_numeric( $u1_has_request ) && $u1_has_request > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    672701                $m1 = new BP_Groups_Member( $u1, $g );
    673702                $m1->promote( 'admin' );
    674703
    675                 self::invite_user_to_group( $u2, $g, $u1 );
    676 
     704                groups_invite_user( array(
     705                        'user_id' => $u2,
     706                        'group_id' => $g,
     707                        'inviter_id' => $u1,
     708                        'send_invite' => 1,
     709                ) );
    677710                groups_join_group( $g, $u2 );
    678711                // Upon joining the group, outstanding invitations should be cleaned up.
    679712                $this->assertEquals( null, groups_check_user_has_invite( $u2, $g, 'any' ) );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    686719        public function test_groups_join_group_cleanup_requests() {
    687720                $u1 = self::factory()->user->create();
    688721                $g = self::factory()->group->create();
    689                 self::create_group_membership_request( $u1, $g );
     722
     723                groups_send_membership_request( array(
     724                        'user_id' => $u1,
     725                        'group_id' => $g
     726                ) );
    690727
    691728                groups_join_group( $g, $u1 );
    692729                // Upon joining the group, outstanding requests should be cleaned up.
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    825862        public function test_groups_get_invites_for_user() {
    826863                $u1 = self::factory()->user->create();
    827864                $u2 = self::factory()->user->create();
    828                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    829                 $g2 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    830                 $g3 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    831 
    832                 self::invite_user_to_group( $u2, $g1, $u1 );
    833                 self::invite_user_to_group( $u2, $g2, $u1 );
    834                 self::invite_user_to_group( $u2, $g3, $u1 );
     865                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     866                $g2 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     867                $g3 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    835868
     869                groups_invite_user( array(
     870                        'user_id' => $u2,
     871                        'group_id' => $g1,
     872                        'inviter_id' => $u1,
     873                        'send_invite' => 1,
     874                ) );
     875                groups_invite_user( array(
     876                        'user_id' => $u2,
     877                        'group_id' => $g2,
     878                        'inviter_id' => $u1,
     879                        'send_invite' => 1,
     880                ) );
     881                groups_invite_user( array(
     882                        'user_id' => $u2,
     883                        'group_id' => $g3,
     884                        'inviter_id' => $u1,
     885                        'send_invite' => 1,
     886                ) );
    836887                $groups = groups_get_invites_for_user( $u2 );
    837888
    838889                $this->assertEqualSets( array( $g1, $g2, $g3 ), wp_list_pluck( $groups['groups'], 'id' ) );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    848899
    849900                $u1 = self::factory()->user->create();
    850901                $u2 = self::factory()->user->create();
    851                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    852                 $g2 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    853                 $g3 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     902                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     903                $g2 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     904                $g3 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    854905
    855                 self::invite_user_to_group( $u2, $g1, $u1 );
    856                 self::invite_user_to_group( $u2, $g2, $u1 );
    857                 self::invite_user_to_group( $u2, $g3, $u1 );
     906                groups_invite_user( array(
     907                        'user_id' => $u2,
     908                        'group_id' => $g1,
     909                        'inviter_id' => $u1,
     910                        'send_invite' => 1,
     911                ) );
     912                groups_invite_user( array(
     913                        'user_id' => $u2,
     914                        'group_id' => $g2,
     915                        'inviter_id' => $u1,
     916                        'send_invite' => 1,
     917                ) );
     918                groups_invite_user( array(
     919                        'user_id' => $u2,
     920                        'group_id' => $g3,
     921                        'inviter_id' => $u1,
     922                        'send_invite' => 1,
     923                ) );
    858924
    859925                $this->set_current_user( $u2 );
    860926                $groups = groups_get_invites_for_user();
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    871937        public function test_groups_get_invites_for_user_with_exclude() {
    872938                $u1 = self::factory()->user->create();
    873939                $u2 = self::factory()->user->create();
    874                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    875                 $g2 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    876                 $g3 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     940                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     941                $g2 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     942                $g3 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    877943
    878                 self::invite_user_to_group( $u2, $g1, $u1 );
    879                 self::invite_user_to_group( $u2, $g2, $u1 );
    880                 self::invite_user_to_group( $u2, $g3, $u1 );
     944                groups_invite_user( array(
     945                        'user_id' => $u2,
     946                        'group_id' => $g1,
     947                        'inviter_id' => $u1,
     948                        'send_invite' => 1,
     949                ) );
     950                groups_invite_user( array(
     951                        'user_id' => $u2,
     952                        'group_id' => $g2,
     953                        'inviter_id' => $u1,
     954                        'send_invite' => 1,
     955                ) );
     956                groups_invite_user( array(
     957                        'user_id' => $u2,
     958                        'group_id' => $g3,
     959                        'inviter_id' => $u1,
     960                        'send_invite' => 1,
     961                ) );
    881962
    882963                $groups = groups_get_invites_for_user( $u2, false, false, array( $g2 ) );
    883964                $this->assertEqualSets( array( $g1, $g3 ), wp_list_pluck( $groups['groups'], 'id' ) );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    891972        public function test_groups_get_invite_count_for_user() {
    892973                $u1 = self::factory()->user->create();
    893974                $u2 = self::factory()->user->create();
    894                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    895                 $g2 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    896                 $g3 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     975                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     976                $g2 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     977                $g3 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    897978
    898                 self::invite_user_to_group( $u2, $g1, $u1 );
    899                 self::invite_user_to_group( $u2, $g2, $u1 );
    900                 self::invite_user_to_group( $u2, $g3, $u1 );
     979                groups_invite_user( array(
     980                        'user_id' => $u2,
     981                        'group_id' => $g1,
     982                        'inviter_id' => $u1,
     983                        'send_invite' => 1,
     984                ) );
     985                groups_invite_user( array(
     986                        'user_id' => $u2,
     987                        'group_id' => $g2,
     988                        'inviter_id' => $u1,
     989                        'send_invite' => 1,
     990                ) );
     991                groups_invite_user( array(
     992                        'user_id' => $u2,
     993                        'group_id' => $g3,
     994                        'inviter_id' => $u1,
     995                        'send_invite' => 1,
     996                ) );
    901997
    902998                $this->assertEquals( 3, groups_get_invite_count_for_user( $u2 ) );
    903999        }
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9101006        public function test_groups_get_invite_count_for_user_ignore_drafts() {
    9111007                $u1 = self::factory()->user->create();
    9121008                $u2 = self::factory()->user->create();
    913                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1009                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    9141010
    9151011                // Create draft invitation.
    9161012                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9331029        public function test_groups_invite_user() {
    9341030                $u1 = self::factory()->user->create();
    9351031                $u2 = self::factory()->user->create();
    936                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1032                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    9371033
    9381034                // Create draft invitation
    9391035                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9571053        public function test_groups_send_invites() {
    9581054                $u1 = self::factory()->user->create();
    9591055                $u2 = self::factory()->user->create();
    960                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1056                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    9611057
    9621058                // Create draft invitation
    9631059                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9691065                ) );
    9701066
    9711067                // Send the invitation
    972                 groups_send_invites( $u1, $g1 );
     1068                groups_send_invites( array(
     1069                        'group_id'   => $g1,
     1070                        'inviter_id' => $u1,
     1071                ) );
    9731072
    9741073                // Check that the invitation has been sent.
    9751074                $sent = groups_check_user_has_invite( $u2, $g1, $type = 'sent' );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9771076        }
    9781077
    9791078        /**
    980          * @group groups_accept_invite
     1079         * @group groups_send_invites
    9811080         * @group group_invitations
    9821081         * @group group_membership
     1082         * @expectedDeprecated groups_send_invites
    9831083         */
    984         public function test_groups_accept_invite() {
     1084        public function test_groups_send_invites_deprecated_args() {
    9851085                $u1 = self::factory()->user->create();
    9861086                $u2 = self::factory()->user->create();
    987                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1087                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    9881088
    9891089                // Create draft invitation
    9901090                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    9981098                // Send the invitation
    9991099                groups_send_invites( $u1, $g1 );
    10001100
     1101                // Check that the invitation has been sent.
     1102                $sent = groups_check_user_has_invite( $u2, $g1, $type = 'sent' );
     1103                $this->assertTrue( is_numeric( $sent ) && $sent > 0 );
     1104        }
     1105
     1106        /**
     1107         * @group groups_accept_invite
     1108         * @group group_invitations
     1109         * @group group_membership
     1110         */
     1111        public function test_groups_accept_invite() {
     1112                $u1 = self::factory()->user->create();
     1113                $u2 = self::factory()->user->create();
     1114                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
     1115
     1116                // Create draft invitation
     1117                groups_invite_user( array(
     1118                        'user_id'       => $u2,
     1119                        'group_id'      => $g1,
     1120                        'inviter_id'    => $u1,
     1121                        'date_modified' => bp_core_current_time(),
     1122                        'is_confirmed'  => 0,
     1123                        'send_invite'   => 1
     1124                ) );
     1125
    10011126                // Accept the invitation
    10021127                groups_accept_invite( $u2, $g1 );
    10031128
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    10171142        public function test_groups_accept_invite_removes_membership_requests() {
    10181143                $u1 = self::factory()->user->create();
    10191144                $u2 = self::factory()->user->create();
    1020                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1145                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    10211146
    10221147                // Create draft invitation
    10231148                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    10291154                ) );
    10301155
    10311156                // Create membership request
    1032                 groups_send_membership_request( $u2, $g1 );
     1157                $request_id = groups_send_membership_request( array(
     1158                        'user_id'       => $u2,
     1159                        'group_id'      => $g1,
     1160                ) );
     1161
    10331162                $request = groups_check_for_membership_request( $u2, $g1 );
     1163
    10341164                $this->assertTrue( is_numeric( $request ) && $request > 0 );
    10351165
    10361166                // Send the invitation
    1037                 groups_send_invites( $u1, $g1 );
     1167                groups_send_invites( array(
     1168                        'group_id'   => $g1,
     1169                        'inviter_id' => $u1,
     1170                ) );
    10381171
    10391172                // Accept the invitation
    10401173                groups_accept_invite( $u2, $g1 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    10521185        public function test_groups_sent_invite_plus_request_equals_member() {
    10531186                $u1 = self::factory()->user->create();
    10541187                $u2 = self::factory()->user->create();
    1055                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1188                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    10561189
    10571190                // Create draft invitation
    10581191                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    10601193                        'group_id'      => $g1,
    10611194                        'inviter_id'    => $u1,
    10621195                        'date_modified' => bp_core_current_time(),
    1063                         'is_confirmed'  => 0
     1196                        'is_confirmed'  => 0,
     1197                        'send_invite'   => 1
    10641198                ) );
    10651199
    1066                 // Send the invitation
    1067                 groups_send_invites( $u1, $g1 );
    1068 
    10691200                // Create membership request
    1070                 groups_send_membership_request( $u2, $g1 );
     1201                groups_send_membership_request( array(
     1202                        'user_id' => $u2,
     1203                        'group_id' => $g1
     1204                ) );
    10711205
    10721206                // User should now be a group member
    10731207                $member = groups_is_user_member( $u2, $g1 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    10831217                $u1 = self::factory()->user->create();
    10841218                $u2 = self::factory()->user->create();
    10851219                $u3 = self::factory()->user->create();
    1086                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1220                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    10871221
    1088                 self::invite_user_to_group( $u2, $g1, $u1 );
    1089                 self::invite_user_to_group( $u3, $g1, $u1 );
     1222                groups_invite_user( array(
     1223                        'user_id' => $u2,
     1224                        'group_id' => $g1,
     1225                        'inviter_id' => $u1,
     1226                        'send_invite' => 1,
     1227                ) );
     1228                groups_invite_user( array(
     1229                        'user_id' => $u3,
     1230                        'group_id' => $g1,
     1231                        'inviter_id' => $u1,
     1232                        'send_invite' => 1,
     1233                ) );
    10901234
    10911235                groups_delete_all_group_invites( $g1 );
    10921236
    10931237                // Get group invitations of any type, from any user in the group.
    1094                 $invitees = new BP_Group_Member_Query( array(
     1238
     1239                $invitees = groups_get_invites( array(
    10951240                        'group_id'     => $g1,
    1096                         'is_confirmed' => 0,
    1097                         'invite_sent'  => null,
    1098                         'inviter_id'   => 'any',
     1241                        'invite_sent'  => 'all',
    10991242                ) );
    11001243
    1101                 $this->assertTrue( empty( $invitees->results ) );
     1244                $this->assertTrue( empty( $invitees ) );
    11021245        }
    11031246
    11041247        /**
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    11291272         */
    11301273        public function test_groups_send_invites_fail_on_empty_user_id() {
    11311274                $u1 = self::factory()->user->create();
    1132                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1275                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    11331276
    11341277                // Create draft invitation with empty inviter_id
    11351278                $invite_created = groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    11511294        public function test_groups_send_invites_fail_on_empty_inviter_id() {
    11521295                $u1 = self::factory()->user->create();
    11531296                $u2 = self::factory()->user->create();
    1154                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1297                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    11551298
    11561299                // Create draft invitation with empty inviter_id
    11571300                $invite_created = groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    11741317        public function test_groups_get_invites_for_group_with_sent_parameter() {
    11751318                $u1 = self::factory()->user->create();
    11761319                $u2 = self::factory()->user->create();
    1177                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1320                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    11781321
    11791322                // Create draft invitation
    11801323                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    11821325                        'group_id'      => $g1,
    11831326                        'inviter_id'    => $u1,
    11841327                        'date_modified' => bp_core_current_time(),
    1185                         'is_confirmed'  => 0
     1328                        'is_confirmed'  => 0,
     1329                        'send_invite'   => 1
    11861330                ) );
    11871331
    1188                 // Send the invitation; this will set the 'invite_sent' value to 1.
    1189                 groups_send_invites( $u1, $g1 );
    1190 
    11911332                // Default groups_get_invites_for_group() call
    11921333                $i = groups_get_invites_for_group( $u1, $g1 );
    11931334                $this->assertEqualSets( array( $u2 ), $i );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12081349         */
    12091350        public function test_groups_send_membership_request() {
    12101351                $u1 = self::factory()->user->create();
    1211                 $g1 = self::factory()->group->create();
     1352                $g1 = self::factory()->group->create( array( 'status' => 'private' ) );
     1353
     1354                // Create membership request
     1355                groups_send_membership_request( array(
     1356                        'user_id' => $u1,
     1357                        'group_id' => $g1
     1358                ) );
     1359
     1360                $request = groups_check_for_membership_request( $u1, $g1 );
     1361                $this->assertTrue( is_numeric( $request ) && $request > 0 );
     1362        }
     1363
     1364        /**
     1365         * @group groups_send_membership_request
     1366         * @group group_membership_requests
     1367         * @group group_membership
     1368         * @expectedDeprecated groups_send_membership_request
     1369         */
     1370        public function test_groups_send_membership_request_deprecated_args() {
     1371                $u1 = self::factory()->user->create();
     1372                $g1 = self::factory()->group->create( array( 'status' => 'private' ) );
    12121373
    12131374                // Create membership request
    12141375                groups_send_membership_request( $u1, $g1 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12241385         */
    12251386        public function test_groups_accept_membership_request_by_membership_id() {
    12261387                $u1 = self::factory()->user->create();
    1227                 $g1 = self::factory()->group->create();
     1388                $g1 = self::factory()->group->create( array( 'status' => 'private' ) );
    12281389
    12291390                // Create membership request
    1230                 groups_send_membership_request( $u1, $g1 );
     1391                groups_send_membership_request( array(
     1392                        'user_id' => $u1,
     1393                        'group_id' => $g1
     1394                ) );
    12311395
    12321396                // Get group invitations of any type, from any user in the group.
    12331397                $member = new BP_Groups_Member( $u1, $g1 );
    12341398
    1235                 groups_accept_membership_request( $member->id );
     1399                groups_accept_membership_request( false, $u1, $g1 );
    12361400
    12371401                // User should now be a group member.
    12381402                $member = groups_is_user_member( $u1, $g1 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12471411         */
    12481412        public function test_groups_accept_membership_request_by_user_id_group_id() {
    12491413                $u1 = self::factory()->user->create();
    1250                 $g1 = self::factory()->group->create();
     1414                $g1 = self::factory()->group->create( array( 'status' => 'private' ) );
    12511415
    12521416                // Create membership request
    1253                 groups_send_membership_request( $u1, $g1 );
     1417                groups_send_membership_request( array(
     1418                        'user_id' => $u1,
     1419                        'group_id' => $g1
     1420                ) );
    12541421
    12551422                groups_accept_membership_request( null, $u1, $g1 );
    12561423
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12681435        public function test_groups_membership_request_plus_invite_equals_member() {
    12691436                $u1 = self::factory()->user->create();
    12701437                $u2 = self::factory()->user->create();
    1271                 $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     1438                $g1 = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    12721439
    12731440                // Create membership request
    1274                 groups_send_membership_request( $u2, $g1 );
     1441                groups_send_membership_request( array(
     1442                        'user_id' => $u2,
     1443                        'group_id' => $g1
     1444                ) );
    12751445
    12761446                // Create draft invitation
    12771447                groups_invite_user( array(
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12791449                        'group_id'      => $g1,
    12801450                        'inviter_id'    => $u1,
    12811451                        'date_modified' => bp_core_current_time(),
    1282                         'is_confirmed'  => 0
     1452                        'is_confirmed'  => 0,
     1453                        'send_invite'   => 1
    12831454                ) );
    12841455
    1285                 // Send the invitation
    1286                 groups_send_invites( $u1, $g1 );
    1287 
    12881456                // User should now be a group member
    12891457                $member = groups_is_user_member( $u2, $g1 );
    12901458                $this->assertTrue( is_numeric( $member ) && $member > 0 );
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    12991467                $u1 = self::factory()->user->create();
    13001468                $u2 = self::factory()->user->create();
    13011469                $u3 = self::factory()->user->create();
    1302                 $g1 = self::factory()->group->create();
     1470                $g1 = self::factory()->group->create( array( 'status' => 'private' ) );
    13031471
    13041472                // Create membership request
    1305                 groups_send_membership_request( $u1, $g1 );
    1306                 groups_send_membership_request( $u2, $g1 );
    1307                 groups_send_membership_request( $u3, $g1 );
     1473                groups_send_membership_request( array(
     1474                        'user_id' => $u1,
     1475                        'group_id' => $g1
     1476                ) );
     1477                groups_send_membership_request( array(
     1478                        'user_id' => $u2,
     1479                        'group_id' => $g1
     1480                ) );
     1481                groups_send_membership_request( array(
     1482                        'user_id' => $u3,
     1483                        'group_id' => $g1
     1484                ) );
    13081485
    13091486                groups_accept_all_pending_membership_requests( $g1 );
    13101487
    class BP_Tests_BP_Groups_Member_TestCases extends BP_UnitTestCase { 
    14021579                $this->assertSame( self::$group_ids[0], $memberships[0]->group_id );
    14031580        }
    14041581
    1405         /**
    1406          * @ticket BP7859
    1407          */
    1408         public function test_get_user_memberships_type_pending_request() {
    1409                 groups_join_group( self::$group_ids[0], self::$user_ids[0] );
    1410                 groups_send_membership_request( self::$user_ids[0], self::$group_ids[1] );
    1411 
    1412                 $memberships = BP_Groups_Member::get_user_memberships( self::$user_ids[0], array(
    1413                         'type' => 'pending_request',
    1414                 ) );
    1415 
    1416                 $this->assertCount( 1, $memberships );
    1417                 $this->assertSame( self::$group_ids[1], $memberships[0]->group_id );
    1418         }
    1419 
    1420         /**
    1421          * @ticket BP7859
    1422          */
    1423         public function test_get_user_memberships_type_pending_received_invitation() {
    1424                 groups_join_group( self::$group_ids[0], self::$user_ids[0] );
    1425                 groups_invite_user( array(
    1426                         'user_id'    => self::$user_ids[0],
    1427                         'group_id'   => self::$group_ids[1],
    1428                         'inviter_id' => self::$user_ids[1],
    1429                 ) );
    1430 
    1431                 $memberships = BP_Groups_Member::get_user_memberships( self::$user_ids[0], array(
    1432                         'type' => 'pending_received_invitation',
    1433                 ) );
    1434 
    1435                 $this->assertCount( 1, $memberships );
    1436                 $this->assertSame( self::$group_ids[1], $memberships[0]->group_id );
    1437         }
    1438 
    1439         /**
    1440          * @ticket BP7859
    1441          */
    1442         public function test_get_user_memberships_type_pending_sent_invitation() {
    1443                 groups_join_group( self::$group_ids[0], self::$user_ids[0] );
    1444                 groups_invite_user( array(
    1445                         'user_id'    => self::$user_ids[1],
    1446                         'group_id'   => self::$group_ids[1],
    1447                         'inviter_id' => self::$user_ids[0],
    1448                 ) );
    1449 
    1450                 $memberships = BP_Groups_Member::get_user_memberships( self::$user_ids[0], array(
    1451                         'type' => 'pending_sent_invitation',
    1452                 ) );
    1453 
    1454                 $this->assertCount( 1, $memberships );
    1455                 $this->assertSame( self::$group_ids[1], $memberships[0]->group_id );
    1456         }
    1457 
    14581582        /**
    14591583         * @ticket BP7476
    14601584         */
  • tests/phpunit/testcases/groups/functions.php

    diff --git tests/phpunit/testcases/groups/functions.php tests/phpunit/testcases/groups/functions.php
    index c4a24592a..ee04ef6a0 100644
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    1212                self::$user_ids  = $factory->user->create_many( 3 );
    1313                self::$group_ids = $factory->group->create_many( 2, array(
    1414                        'creator_id' => self::$user_ids[2],
     15                        'status'     => 'private'
    1516                ) );
    1617        }
    1718
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    138139                $this->set_current_user( $u2 );
    139140
    140141                $g = self::factory()->group->create();
    141                 groups_send_membership_request( $u1, $g );
     142                groups_send_membership_request( array(
     143                        'user_id'       => $u1,
     144                        'group_id'      => $g,
     145                ) );
    142146
    143147                groups_accept_membership_request( 0, $u1, $g );
    144148
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    262266                $u2 = self::factory()->user->create();
    263267                $g = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    264268
    265                 groups_send_membership_request( $u2, $g );
     269                groups_send_membership_request( array(
     270                        'user_id'       => $u2,
     271                        'group_id'      => $g,
     272                ) );
    266273                groups_accept_membership_request( 0, $u2, $g );
    267274
    268275                $this->assertEquals( 2, groups_get_groupmeta( $g, 'total_member_count' ) );
    Bar!'; 
    632639        public function test_get_invite_count_for_user() {
    633640                $u1 = self::factory()->user->create();
    634641                $u2 = self::factory()->user->create();
    635                 $g = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     642                $g = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    636643
    637644                // create invitation
    638645                groups_invite_user( array(
    639646                        'user_id'    => $u2,
    640647                        'group_id'   => $g,
    641648                        'inviter_id' => $u1,
     649                        'send_invite' => 1
    642650                ) );
    643651
    644                 // send the invite
    645                 // this function is imperative to set the 'invite_sent' flag in the DB
    646                 // why is this separated from groups_invite_user()?
    647                 // @see groups_screen_group_invite()
    648                 groups_send_invites( $u1, $g );
    649 
    650652                // assert invite count
    651653                $this->assertEquals( 1, groups_get_invite_count_for_user( $u2 ) );
    652654
    Bar!'; 
    890892         * @ticket BP7698
    891893         */
    892894        public function test_bp_groups_pending_requests_personal_data_exporter() {
    893                 groups_send_membership_request( self::$user_ids[0], self::$group_ids[0] );
     895                groups_send_membership_request( array(
     896                        'user_id'       => self::$user_ids[0],
     897                        'group_id'      => self::$group_ids[0],
     898                ) );
    894899
    895900                $test_user = new WP_User( self::$user_ids[0] );
    896901
  • tests/phpunit/testcases/groups/functions/bpGetUserGroups.php

    diff --git tests/phpunit/testcases/groups/functions/bpGetUserGroups.php tests/phpunit/testcases/groups/functions/bpGetUserGroups.php
    index acf28c6b1..ccdb888ba 100644
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    541541                $server_name = isset( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : null;
    542542                $_SERVER['SERVER_NAME'] = '';
    543543
    544                 groups_send_membership_request( self::$user, self::$groups[2] );
     544                groups_send_membership_request( array(
     545                        'user_id'       => self::$user,
     546                        'group_id'      => self::$groups[2],
     547                ) );
    545548
    546549                // Populate cache.
    547550                $g1 = bp_get_user_groups( self::$user );
    548551
    549552                $m = new BP_Groups_Member( self::$user, self::$groups[2] );
    550553
    551                 groups_accept_membership_request( $m->id, self::$user, self::$groups[2] );
     554                groups_accept_membership_request( false, self::$user, self::$groups[2] );
    552555
    553556                // For `wp_mail()`.
    554557                if ( is_null( $server_name ) ) {
  • tests/phpunit/testcases/groups/functions/groupsIsUser.php

    diff --git tests/phpunit/testcases/groups/functions/groupsIsUser.php tests/phpunit/testcases/groups/functions/groupsIsUser.php
    index f7d6dd356..ef35382c9 100644
    class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase { 
    2121                ) );
    2222                self::$groups = $f->group->create_many( 3, array(
    2323                        'creator_id' => self::$admin_user,
     24                        'status'     => 'private'
    2425                ) );
    2526
    2627                $now = time();
    class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase { 
    173174                $i = groups_invite_user( array(
    174175                        'user_id' => self::$user,
    175176                        'group_id' => self::$groups[1],
    176                         'inviter_id' => 123,
     177                        'inviter_id' => self::$admin_user,
     178                        'send_invite' => 1,
    177179                ) );
    178180
    179                 // Send invite.
    180                 $m = new BP_Groups_Member( self::$user, self::$groups[1] );
    181                 $m->invite_sent = 1;
    182                 $m->save();
    183 
    184181                $this->assertNotEmpty( groups_is_user_invited( self::$user, self::$groups[1] ) );
    185182        }
    186183
    187         public function test_groups_is_user_pending_should_return_false_for_pending_member() {
     184        public function test_groups_is_user_pending_should_return_false_for_invited_member() {
    188185                groups_invite_user( array(
    189186                        'user_id' => self::$user,
    190187                        'group_id' => self::$groups[1],
    191                         'inviter_id' => 123,
     188                        'send_invite' => 1
    192189                ) );
    193190
    194                 // Send invite.
    195                 $m = new BP_Groups_Member( self::$user, self::$groups[1] );
    196                 $m->invite_sent = 1;
    197                 $m->save();
    198 
    199191                $this->assertEquals( false, groups_is_user_pending( self::$user, self::$groups[1] ) );
    200192        }
    201193
    class BP_Tests_Groups_Functions_GroupsIsUser extends BP_UnitTestCase { 
    204196        }
    205197
    206198        public function test_groups_is_user_pending_should_return_true_for_pending_member() {
    207 
    208                 $m                = new BP_Groups_Member;
    209                 $m->group_id      = self::$groups[1];
    210                 $m->user_id       = self::$user;
    211                 $m->inviter_id    = 0;
    212                 $m->is_admin      = 0;
    213                 $m->user_title    = '';
    214                 $m->date_modified = bp_core_current_time();
    215                 $m->is_confirmed  = 0;
    216                 $m->comments      = 'request';
    217                 $m->save();
     199                groups_send_membership_request( array(
     200                        'user_id' => self::$user,
     201                        'group_id' => self::$groups[1],
     202                ) );
    218203
    219204                $this->assertNotEmpty( groups_is_user_pending( self::$user, self::$groups[1] ) );
    220205        }
  • tests/phpunit/testcases/groups/template/bpGroupStatusMessage.php

    diff --git tests/phpunit/testcases/groups/template/bpGroupStatusMessage.php tests/phpunit/testcases/groups/template/bpGroupStatusMessage.php
    index b6d5e1173..bcc1ff3eb 100644
    class BP_Tests_Groups_Template_BpGroupStatusMessage extends BP_UnitTestCase { 
    9898
    9999                $this->set_current_user( $u );
    100100
    101                 groups_send_membership_request( $u, $g );
     101                groups_send_membership_request( array(
     102                        'user_id'  => $u,
     103                        'group_id' => $g
     104                ) );
    102105
    103106                if ( bp_has_groups( array( 'include' => array( $g ) ) ) ) {
    104107                        while ( bp_groups() ) {
    class BP_Tests_Groups_Template_BpGroupStatusMessage extends BP_UnitTestCase { 
    141144                $GLOBALS['groups_template'] = new stdClass;
    142145                $GLOBALS['groups_template']->group = groups_get_group( $groups[0] );
    143146
    144                 groups_send_membership_request( $u, $groups[1] );
     147                groups_send_membership_request( array(
     148                        'user_id' => $u,
     149                        'group_id' => $groups[1]
     150                ) );
    145151
    146152                $group1 = groups_get_group( array(
    147153                        'group_id' => $groups[1],
  • tests/phpunit/testcases/groups/user_can.php

    diff --git tests/phpunit/testcases/groups/user_can.php tests/phpunit/testcases/groups/user_can.php
    index 01b4bd254..fee0706f4 100644
    class BP_Tests_Groups_User_Can_Filter extends BP_UnitTestCase { 
    108108                        'status'      => 'private'
    109109                ) );
    110110                $u1 = $this->factory->user->create();
    111                 groups_send_membership_request( $u1, $g1 );
     111                groups_send_membership_request( array(
     112                        'user_id' => $u1,
     113                        'group_id' => $g1
     114                ) );
    112115
    113116                $this->assertFalse( bp_user_can( $u1, 'groups_request_membership', array( 'group_id' => $g1 ) ) );
    114117        }