Skip to:
Content

BuddyPress.org

Ticket #6210: 6210-0729.diff

File 6210-0729.diff, 199.6 KB (added by dcavins, 6 years ago)

Rebased version.

  • 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 244d1a1f9..bb15a40b5 100644
    function bp_core_install_emails() { 
    540540         */
    541541        do_action( 'bp_core_install_emails' );
    542542}
     543
     544/**
     545 * Install database tables for the Invitations API
     546 *
     547 * @since 5.0.0
     548 *
     549 * @uses bp_core_set_charset()
     550 * @uses bp_core_get_table_prefix()
     551 * @uses dbDelta()
     552 */
     553function bp_core_install_invitations() {
     554        $sql             = array();
     555        $charset_collate = $GLOBALS['wpdb']->get_charset_collate();
     556        $bp_prefix       = bp_core_get_table_prefix();
     557        $sql[] = "CREATE TABLE {$bp_prefix}bp_invitations (
     558                id bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
     559                user_id bigint(20) NOT NULL,
     560                inviter_id bigint(20) NOT NULL,
     561                invitee_email varchar(100) DEFAULT NULL,
     562                class varchar(120) NOT NULL,
     563                item_id bigint(20) NOT NULL,
     564                secondary_item_id bigint(20) DEFAULT NULL,
     565                type varchar(12) NOT NULL DEFAULT 'invite',
     566                content longtext DEFAULT '',
     567                date_modified datetime NOT NULL,
     568                invite_sent tinyint(1) NOT NULL DEFAULT '0',
     569                accepted tinyint(1) NOT NULL DEFAULT '0',
     570                KEY user_id (user_id),
     571                KEY inviter_id (inviter_id),
     572                KEY invitee_email (invitee_email),
     573                KEY class (class),
     574                KEY item_id (item_id),
     575                KEY secondary_item_id (secondary_item_id),
     576                KEY type (type),
     577                KEY invite_sent (invite_sent),
     578                KEY accepted (accepted)
     579                ) {$charset_collate};";
     580        dbDelta( $sql );
     581
     582        /**
     583         * Fires after BuddyPress adds the invitations table.
     584         *
     585         * @since 5.0.0
     586         */
     587        do_action( 'bp_core_install_invitations' );
     588}
  • 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 b2cc9761a..db6d0289e 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_update_to_2_7() { 
    551552 * 5.0.0 update routine.
    552553 *
    553554 * - Make sure the custom visibility is disabled for the default profile field.
     555 * - Create the invitations table.
     556 * - Migrate requests and invitations to the new table.
    554557 *
    555558 * @since 5.0.0
    556559 */
    function bp_update_to_5_0() { 
    579582                        '%s'
    580583                )
    581584        );
     585
     586        bp_core_install_invitations();
     587
     588        if ( bp_is_active( 'groups' ) ) {
     589                bp_groups_migrate_invitations();
     590        }
    582591}
    583592
    584593/**
  • new file src/bp-core/classes/class-bp-invitation-manager.php

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

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

    diff --git src/bp-groups/actions/create.php src/bp-groups/actions/create.php
    index fa196caa7..132429bd1 100644
    function groups_action_create_group() { 
    136136                                }
    137137                        }
    138138
    139                         groups_send_invites( bp_loggedin_user_id(), $bp->groups->new_group_id );
     139                        groups_send_invites( array(     'group_id' => $bp->groups->new_group_id ) );
    140140                }
    141141
    142142                /**
    function groups_action_sort_creation_steps() { 
    337337         * @since 2.3.0
    338338         */
    339339        do_action( 'groups_action_sort_creation_steps' );
    340 }
    341  No newline at end of file
     340}
  • 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..1a3913a59 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_Invitation_Manager();
     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-cache.php

    diff --git src/bp-groups/bp-groups-cache.php src/bp-groups/bp-groups-cache.php
    index b44ea09f6..7d38f3d90 100644
    function bp_groups_clear_user_group_cache_on_membership_save( BP_Groups_Member $ 
    254254add_action( 'groups_member_before_save', 'bp_groups_clear_user_group_cache_on_membership_save' );
    255255add_action( 'groups_member_before_remove', 'bp_groups_clear_user_group_cache_on_membership_save' );
    256256
     257/**
     258 * Clear caches on saving a group invitation or request.
     259 * The save action is called when inserting a new record or using the save() method
     260 * to update an existing record.
     261 *
     262 * @since 5.0.0
     263 *
     264 * @param BP_Invitation object $invitation Characteristics of the invitation just saved.
     265 */
     266function bp_groups_clear_user_group_cache_on_invitation_save( BP_Invitation $invitation ) {
     267        if ( sanitize_key( 'BP_Groups_Invitation_Manager' ) !== $invitation->class ) {
     268                return;
     269        }
     270
     271        wp_cache_delete( $invitation->id, 'bp_groups_invitations_as_memberships' );
     272}
     273add_action( 'bp_invitation_after_save', 'bp_groups_clear_user_group_cache_on_invitation_save', 10, 2 );
     274
     275/**
     276 * Clear caches on invitation deletion or update.
     277 * This also catches changes like sending an invite or marking one as accepted.
     278 *
     279 * @since 5.0.0
     280 *
     281 * @param array $args Associative array of columns/values describing invitations about to be deleted.
     282 */
     283function bp_groups_clear_user_group_cache_on_invitation_change( $args ) {
     284        $args['fields' ] = 'ids';
     285        $affected_invitation_ids = groups_get_invites( $args );
     286        foreach ( $affected_invitation_ids as $invitation_id ) {
     287                wp_cache_delete( $invitation_id, 'bp_groups_invitations_as_memberships' );
     288        }
     289}
     290add_action( 'bp_invitation_before_delete', 'bp_groups_clear_user_group_cache_on_invitation_change' );
     291add_action( 'bp_invitation_before_update', 'bp_groups_clear_user_group_cache_on_invitation_change' );
     292
    257293/**
    258294 * Clear group memberships cache on miscellaneous actions not covered by the 'after_save' hook.
    259295 *
    function bp_groups_clear_user_group_cache_on_other_events( $user_id, $group_id ) 
    269305        wp_cache_delete( $membership->id, 'bp_groups_memberships' );
    270306}
    271307add_action( 'bp_groups_member_before_delete', 'bp_groups_clear_user_group_cache_on_other_events', 10, 2 );
    272 add_action( 'bp_groups_member_before_delete_invite', 'bp_groups_clear_user_group_cache_on_other_events', 10, 2 );
    273 add_action( 'groups_accept_invite', 'bp_groups_clear_user_group_cache_on_other_events', 10, 2 );
    274308
    275309/**
    276310 * Reset cache incrementor for the Groups component.
  • src/bp-groups/bp-groups-filters.php

    diff --git src/bp-groups/bp-groups-filters.php src/bp-groups/bp-groups-filters.php
    index fe4310d1a..a3bd2e70f 100644
    function bp_groups_user_can_filter( $retval, $user_id, $capability, $site_id, $a 
    310310                        * currently be a member or be banned from the group.
    311311                        */
    312312                        $group = groups_get_group( $group_id );
    313                         if ( in_array( bp_get_group_status( $group ), array( 'private', 'hidden' ), true )
    314                                 && ! groups_is_user_member( $user_id, $group->id )
    315                                 && ! groups_is_user_banned( $user_id, $group->id )
    316                         ) {
     313                        if ( ! groups_is_user_member( $user_id, $group->id ) && ! groups_is_user_banned( $user_id, $group->id ) ) {
    317314                                $retval = true;
    318315                        }
    319316                        break;
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index e51263ca1..ad4038451 100644
    function bp_get_user_groups( $user_id, $args = array() ) { 
    949949
    950950        $user_id = intval( $user_id );
    951951
     952        // Standard memberships
    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 bp_get_user_groups( $user_id, $args = array() ) { 
    965966                }
    966967        }
    967968
     969        // Prime the invitations- and requests-as-memberships cache
     970        $invitation_ids = array();
     971        if ( true !== $r['is_confirmed'] || false !== $r['invite_sent'] ) {
     972                $invitation_ids = groups_get_invites( array(
     973                        'user_id'     => $user_id,
     974                        'invite_sent' => 'all',
     975                        'type'        => 'all',
     976                        'fields'      => 'ids'
     977                ) );
     978
     979                // Prime the invitations cache.
     980                $uncached_invitation_ids = bp_get_non_cached_ids( $invitation_ids, 'bp_groups_invitations_as_memberships' );
     981
     982                $uncached_invitations = groups_get_invites( array(
     983                        'ids'         => $uncached_invitation_ids,
     984                        'invite_sent' => 'all',
     985                        'type'        => 'all'
     986                ) );
     987                foreach ( $uncached_invitations as $uncached_invitation ) {
     988                        // Reshape the result as a membership db entry.
     989                        $invitation = new StdClass;
     990                        $invitation->id            = $uncached_invitation->id;
     991                        $invitation->group_id      = $uncached_invitation->item_id;
     992                        $invitation->user_id       = $uncached_invitation->user_id;
     993                        $invitation->inviter_id    = $uncached_invitation->inviter_id;
     994                        $invitation->is_admin      = false;
     995                        $invitation->is_mod            = false;
     996                        $invitation->user_title    = '';
     997                        $invitation->date_modified = $uncached_invitation->date_modified;
     998                        $invitation->comments      = $uncached_invitation->content;
     999                        $invitation->is_confirmed  = false;
     1000                        $invitation->is_banned     = false;
     1001                        $invitation->invite_sent   = $uncached_invitation->invite_sent;
     1002                        wp_cache_set( $uncached_invitation->id, $invitation, 'bp_groups_invitations_as_memberships' );
     1003                }
     1004
     1005        }
     1006
     1007
    9681008        // Assemble filter array for use in `wp_list_filter()`.
    9691009        $filters = wp_array_slice_assoc( $r, array( 'is_confirmed', 'is_banned', 'is_admin', 'is_mod', 'invite_sent' ) );
    9701010        foreach ( $filters as $filter_name => $filter_value ) {
    function bp_get_user_groups( $user_id, $args = array() ) { 
    10061046                $groups[ $group_id ] = $membership;
    10071047        }
    10081048
     1049        // Populate group invitations array from cache, and normalize.
     1050        foreach ( $invitation_ids as $invitation_id ) {
     1051                $invitation = wp_cache_get( $invitation_id, 'bp_groups_invitations_as_memberships' );
     1052
     1053                // Sanity check.
     1054                if ( ! isset( $invitation->group_id ) ) {
     1055                        continue;
     1056                }
     1057
     1058                // Integer values.
     1059                foreach ( $int_keys as $index ) {
     1060                        $invitation->{$index} = intval( $invitation->{$index} );
     1061                }
     1062
     1063                // Boolean values.
     1064                foreach ( $bool_keys as $index ) {
     1065                        $invitation->{$index} = (bool) $invitation->{$index};
     1066                }
     1067
     1068                foreach ( $filters as $filter_name => $filter_value ) {
     1069                        if ( ! isset( $invitation->{$filter_name} ) || $filter_value != $invitation->{$filter_name} ) {
     1070                                continue 2;
     1071                        }
     1072                }
     1073
     1074                $group_id = (int) $invitation->group_id;
     1075
     1076                $groups[ $group_id ] = $invitation;
     1077        }
     1078
    10091079        // By default, results are ordered by membership id.
    10101080        if ( 'group_id' === $r['orderby'] ) {
    10111081                ksort( $groups );
    function groups_is_user_banned( $user_id, $group_id ) { 
    12531323 * Check whether a user has an outstanding invitation to a group.
    12541324 *
    12551325 * @since 2.6.0
     1326 * @since 5.0.0 Added $type parameter.
    12561327 *
    1257  * @param int $user_id ID of the user.
    1258  * @param int $group_id ID of the group.
     1328 * @param int    $user_id  ID of the user.
     1329 * @param int    $group_id ID of the group.
     1330 * @param string $type     If 'sent', results are limited to those invitations
     1331 *                         that have actually been sent (non-draft).
     1332 *                         Possible values: 'sent', 'draft', or 'all' Default: 'sent'.
    12591333 * @return int|bool ID of the membership if the user is invited, otherwise false.
    12601334 */
    1261 function groups_is_user_invited( $user_id, $group_id ) {
    1262         $is_invited = false;
    1263 
    1264         $user_groups = bp_get_user_groups( $user_id, array(
    1265                 'invite_sent' => true,
    1266                 'is_confirmed' => false,
    1267         ) );
    1268 
    1269         if ( isset( $user_groups[ $group_id ] ) ) {
    1270                 $is_invited = $user_groups[ $group_id ]->id;
    1271         }
    1272 
    1273         return $is_invited;
     1335function groups_is_user_invited( $user_id, $group_id, $type = 'sent' ) {
     1336        return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
    12741337}
    12751338
    12761339/**
    function groups_is_user_invited( $user_id, $group_id ) { 
    12831346 * @return int|bool ID of the membership if the user is pending, otherwise false.
    12841347 */
    12851348function groups_is_user_pending( $user_id, $group_id ) {
    1286         $is_pending = false;
    1287 
    1288         $user_groups = bp_get_user_groups( $user_id, array(
    1289                 'invite_sent' => false,
    1290                 'is_confirmed' => false,
    1291         ) );
    1292 
    1293         if ( isset( $user_groups[ $group_id ] ) ) {
    1294                 $is_pending = $user_groups[ $group_id ]->id;
     1349        if ( empty( $user_id ) || empty( $group_id ) ) {
     1350                return false;
    12951351        }
    12961352
    1297         return $is_pending;
     1353        $args = array(
     1354                'user_id'     => $user_id,
     1355                'item_id'     => $group_id,
     1356        );
     1357        $invites_class = new BP_Groups_Invitation_Manager();
     1358
     1359        return $invites_class->request_exists( $args );
    12981360}
    12991361
    13001362/**
    function groups_is_user_creator( $user_id, $group_id ) { 
    13131375/** Group Invitations *********************************************************/
    13141376
    13151377/**
    1316  * Get IDs of users with outstanding invites to a given group from a specified user.
     1378 * Get group objects for groups that a user is currently invited to.
    13171379 *
    13181380 * @since 1.0.0
    13191381 *
    1320  * @param int               $user_id ID of the inviting user.
     1382 * @param int               $user_id ID of the invited user.
    13211383 * @param int|bool          $limit   Limit to restrict to.
    13221384 * @param int|bool          $page    Optional. Page offset of results to return.
    13231385 * @param string|array|bool $exclude Array of comma-separated list of group IDs
    13241386 *                                   to exclude from results.
    1325  * @return array $value IDs of users who have been invited to the group by the
    1326  *                      user but have not yet accepted.
     1387 * @return array {
     1388 *     @type array $groups Array of groups returned by paginated query.
     1389 *     @type int   $total  Count of groups matching query.
     1390 * }
    13271391 */
    13281392function groups_get_invites_for_user( $user_id = 0, $limit = false, $page = false, $exclude = false ) {
    1329 
    1330         if ( empty( $user_id ) )
     1393        if ( empty( $user_id ) ) {
    13311394                $user_id = bp_loggedin_user_id();
     1395        }
     1396
     1397        $group_ids = groups_get_invited_to_group_ids( $user_id );
     1398
     1399        // Remove excluded groups.
     1400        if ( $exclude ) {
     1401                $group_ids = array_diff( $group_ids, wp_parse_id_list( $exclude ) );
     1402        }
     1403
     1404        // Avoid passing an empty array.
     1405        if ( ! $group_ids ) {
     1406                $group_ids = array( 0 );
     1407        }
     1408
     1409        // Get a filtered list of groups.
     1410        $args = array(
     1411                'include'     => $group_ids,
     1412                'show_hidden' => true,
     1413                'per_page'    => $limit,
     1414                'page'        => $page,
     1415        );
     1416        $groups = groups_get_groups( $args );
    13321417
    1333         return BP_Groups_Member::get_invites( $user_id, $limit, $page, $exclude );
     1418        return array( 'groups' => $groups['groups'], 'total' => groups_get_invite_count_for_user( $user_id ) );
    13341419}
    13351420
    13361421/**
    function groups_get_invite_count_for_user( $user_id = 0 ) { 
    13461431                $user_id = bp_loggedin_user_id();
    13471432        }
    13481433
    1349         return BP_Groups_Member::get_invite_count_for_user( $user_id );
     1434        return count( groups_get_invited_to_group_ids( $user_id ) );
     1435}
     1436
     1437/**
     1438 * Get an array of group IDs to which a user is invited.
     1439 *
     1440 * @since 5.0.0
     1441 *
     1442 * @param int $user_id The user ID.
     1443 *
     1444 * @return array Array of group IDs.
     1445 */
     1446 function groups_get_invited_to_group_ids( $user_id = 0 ) {
     1447        if ( empty( $user_id ) ) {
     1448                $user_id = bp_loggedin_user_id();
     1449        }
     1450
     1451        $group_ids = groups_get_invites( array(
     1452                'user_id'     => $user_id,
     1453                'invite_sent' => 'sent',
     1454                'fields'      => 'item_ids'
     1455        ) );
     1456
     1457        return array_unique( $group_ids );
    13501458}
    13511459
    13521460/**
    function groups_get_invite_count_for_user( $user_id = 0 ) { 
    13621470 *                                 ID of the logged-in user.
    13631471 *     @type string $date_modified Optional. Modified date for the invitation.
    13641472 *                                 Default: current date/time.
    1365  *     @type bool   $is_confirmed  Optional. Whether the invitation should be
    1366  *                                 marked confirmed. Default: false.
     1473 *     @type string $content       Optional. Message to invitee.
     1474 *     @type bool   $send_invite   Optional. Whether the invitation should be
     1475 *                                 sent now. Default: false.
    13671476 * }
    13681477 * @return bool True on success, false on failure.
    13691478 */
    13701479function groups_invite_user( $args = '' ) {
    13711480
    1372         $args = bp_parse_args( $args, array(
     1481        $r = bp_parse_args( $args, array(
    13731482                'user_id'       => false,
    13741483                'group_id'      => false,
    13751484                'inviter_id'    => bp_loggedin_user_id(),
    13761485                'date_modified' => bp_core_current_time(),
    1377                 'is_confirmed'  => 0
     1486                'content'       => '',
     1487                'send_invite'   => 0
    13781488        ), 'groups_invite_user' );
    1379         extract( $args, EXTR_SKIP );
    13801489
    1381         if ( ! $user_id || ! $group_id || ! $inviter_id ) {
    1382                 return false;
    1383         }
    1384 
    1385         // If the user has already requested membership, accept the request.
    1386         if ( $membership_id = groups_check_for_membership_request( $user_id, $group_id ) ) {
    1387                 groups_accept_membership_request( $membership_id, $user_id, $group_id );
    1388 
    1389         // Otherwise, create a new invitation.
    1390         } elseif ( ! groups_is_user_member( $user_id, $group_id ) && ! groups_check_user_has_invite( $user_id, $group_id, 'all' ) ) {
    1391                 $invite                = new BP_Groups_Member;
    1392                 $invite->group_id      = $group_id;
    1393                 $invite->user_id       = $user_id;
    1394                 $invite->date_modified = $date_modified;
    1395                 $invite->inviter_id    = $inviter_id;
    1396                 $invite->is_confirmed  = $is_confirmed;
     1490        $inv_args = array(
     1491                'user_id'       => $r['user_id'],
     1492                'item_id'       => $r['group_id'],
     1493                'inviter_id'    => $r['inviter_id'],
     1494                'date_modified' => $r['date_modified'],
     1495                'content'       => $r['content'],
     1496                'send_invite'   => $r['send_invite']
     1497        );
    13971498
    1398                 if ( !$invite->save() )
    1399                         return false;
     1499        // Create the unsent invitataion.
     1500        $invites_class = new BP_Groups_Invitation_Manager();
     1501        $created       = $invites_class->add_invitation( $inv_args );
    14001502
    1401                 /**
    1402                 * Fires after the creation of a new group invite.
    1403                 *
    1404                 * @since 1.0.0
    1405                 *
    1406                  * @param array $args Array of parsed arguments for the group invite.
    1407                  */
    1408                 do_action( 'groups_invite_user', $args );
    1409         }
     1503        /**
     1504        * Fires after the creation of a new group invite.
     1505        *
     1506        * @since 1.0.0
     1507        *
     1508         * @param array    $r      Array of parsed arguments for the group invite.
     1509         * @param int|bool $created The ID of the invitation or false if it couldn't be created.
     1510         */
     1511        do_action( 'groups_invite_user', $r, $created );
    14101512
    1411         return true;
     1513        return $created;
    14121514}
    14131515
    14141516/**
    14151517 * Uninvite a user from a group.
    14161518 *
    1417  * Functionally, this is equivalent to removing a user from a group.
    1418  *
    14191519 * @since 1.0.0
    14201520 *
    14211521 * @param int $user_id  ID of the user.
    14221522 * @param int $group_id ID of the group.
     1523 * @param int $inviter_id ID of the inviter.
    14231524 * @return bool True on success, false on failure.
    14241525 */
    1425 function groups_uninvite_user( $user_id, $group_id ) {
    1426 
    1427         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1526function groups_uninvite_user( $user_id, $group_id, $inviter_id = false ) {
     1527        if ( empty( $user_id ) || empty( $group_id ) ) {
    14281528                return false;
     1529        }
    14291530
    1430         /**
    1431          * Fires after uninviting a user from a group.
    1432          *
    1433          * @since 1.0.0
    1434          *
    1435          * @param int $group_id ID of the group being uninvited from.
    1436          * @param int $user_id  ID of the user being uninvited.
    1437          */
    1438         do_action( 'groups_uninvite_user', $group_id, $user_id );
     1531        $invites_class = new BP_Groups_Invitation_Manager();
     1532        $success       = $invites_class->delete( array(
     1533                'user_id'    => $user_id,
     1534                'item_id'    => $group_id,
     1535                'inviter_id' => $inviter_id,
     1536        ) );
    14391537
    1440         return true;
     1538        if ( $success ) {
     1539                /**
     1540                 * Fires after uninviting a user from a group.
     1541                 *
     1542                 * @since 1.0.0
     1543                 * @since 2.7.0 Added $inviter_id parameter
     1544                 *
     1545                 * @param int $group_id    ID of the group being uninvited from.
     1546                 * @param int $user_id     ID of the user being uninvited.
     1547                 * @param int $inviter_id  ID of the inviter.
     1548                 */
     1549                do_action( 'groups_uninvite_user', $group_id, $user_id, $inviter_id );
     1550        }
     1551
     1552        return $success;
    14411553}
    14421554
    14431555/**
    function groups_uninvite_user( $user_id, $group_id ) { 
    14521564 * @return bool True when the user is a member of the group, otherwise false.
    14531565 */
    14541566function groups_accept_invite( $user_id, $group_id ) {
     1567        $invites_class = new BP_Groups_Invitation_Manager();
     1568        $args = array(
     1569                'user_id'     => $user_id,
     1570                'item_id'     => $group_id,
     1571                'invite_sent' => 'sent',
     1572        );
    14551573
    1456         // If the user is already a member (because BP at one point allowed two invitations to
    1457         // slip through), delete all existing invitations/requests and return true.
    1458         if ( groups_is_user_member( $user_id, $group_id ) ) {
    1459                 if ( groups_check_user_has_invite( $user_id, $group_id ) ) {
    1460                         groups_delete_invite( $user_id, $group_id );
    1461                 }
    1462 
    1463                 if ( groups_check_for_membership_request( $user_id, $group_id ) ) {
    1464                         groups_delete_membership_request( null, $user_id, $group_id );
    1465                 }
    1466 
    1467                 return true;
    1468         }
    1469 
    1470         $member = new BP_Groups_Member( $user_id, $group_id );
    1471 
    1472         // Save the inviter ID so that we can pass it to the action below.
    1473         $inviter_id = $member->inviter_id;
    1474 
    1475         $member->accept_invite();
    1476 
    1477         if ( !$member->save() ) {
    1478                 return false;
    1479         }
    1480 
    1481         // Remove request to join.
    1482         if ( $member->check_for_membership_request( $user_id, $group_id ) ) {
    1483                 $member->delete_request( $user_id, $group_id );
    1484         }
    1485 
    1486         // Modify group meta.
    1487         groups_update_groupmeta( $group_id, 'last_activity', bp_core_current_time() );
    1488 
    1489         /**
    1490          * Fires after a user has accepted a group invite.
    1491          *
    1492          * @since 1.0.0
    1493          * @since 2.8.0 The $inviter_id arg was added.
    1494          *
    1495          * @param int $user_id    ID of the user who accepted the group invite.
    1496          * @param int $group_id   ID of the group being accepted to.
    1497          * @param int $inviter_id ID of the user who invited this user to the group.
    1498          */
    1499         do_action( 'groups_accept_invite', $user_id, $group_id, $inviter_id );
    1500 
    1501         return true;
     1574        return $invites_class->accept_invitation( $args );
    15021575}
    15031576
    15041577/**
    15051578 * Reject a group invitation.
    15061579 *
    15071580 * @since 1.0.0
     1581 * @since 5.0.0 The $inviter_id arg was added.
     1582 *
     1583 * @param int $user_id    ID of the user.
     1584 * @param int $group_id   ID of the group.
     1585 * @param int $inviter_id ID of the inviter.
    15081586 *
    1509  * @param int $user_id  ID of the user.
    1510  * @param int $group_id ID of the group.
    15111587 * @return bool True on success, false on failure.
    15121588 */
    1513 function groups_reject_invite( $user_id, $group_id ) {
    1514         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1589function groups_reject_invite( $user_id, $group_id, $inviter_id = false ) {
     1590        if ( empty( $user_id ) || empty( $group_id ) ) {
    15151591                return false;
     1592        }
     1593
     1594        $invites_class = new BP_Groups_Invitation_Manager();
     1595        $success       = $invites_class->delete( array(
     1596                'user_id'    => $user_id,
     1597                'item_id'    => $group_id,
     1598                'inviter_id' => $inviter_id,
     1599        ) );
    15161600
    15171601        /**
    15181602         * Fires after a user rejects a group invitation.
    15191603         *
    15201604         * @since 1.0.0
     1605         * @since 5.0.0 The $inviter_id arg was added.
    15211606         *
    1522          * @param int $user_id  ID of the user rejecting the invite.
    1523          * @param int $group_id ID of the group being rejected.
     1607         * @param int $user_id    ID of the user rejecting the invite.
     1608         * @param int $group_id   ID of the group being rejected.
     1609         * @param int $inviter_id ID of the inviter.
    15241610         */
    1525         do_action( 'groups_reject_invite', $user_id, $group_id );
     1611        do_action( 'groups_reject_invite', $user_id, $group_id, $inviter_id );
    15261612
    1527         return true;
     1613        return $success;
    15281614}
    15291615
    15301616/**
    15311617 * Delete a group invitation.
    15321618 *
    15331619 * @since 1.0.0
     1620 * @since 5.0.0 The $inviter_id arg was added.
    15341621 *
    15351622 * @param int $user_id  ID of the invited user.
    15361623 * @param int $group_id ID of the group.
     1624 * @param int $inviter_id ID of the inviter.
     1625 *
    15371626 * @return bool True on success, false on failure.
    15381627 */
    1539 function groups_delete_invite( $user_id, $group_id ) {
    1540         if ( ! BP_Groups_Member::delete_invite( $user_id, $group_id ) )
     1628function groups_delete_invite( $user_id, $group_id, $inviter_id = false ) {
     1629        if ( empty( $user_id ) || empty( $group_id ) ) {
    15411630                return false;
     1631        }
     1632
     1633        $invites_class = new BP_Groups_Invitation_Manager();
     1634        $success       = $invites_class->delete( array(
     1635                'user_id'    => $user_id,
     1636                'item_id'    => $group_id,
     1637                'inviter_id' => $inviter_id,
     1638        ) );
    15421639
    15431640        /**
    15441641         * Fires after the deletion of a group invitation.
    15451642         *
    15461643         * @since 1.9.0
     1644         * @since 5.0.0 The $inviter_id arg was added.
    15471645         *
    15481646         * @param int $user_id  ID of the user whose invitation is being deleted.
    15491647         * @param int $group_id ID of the group whose invitation is being deleted.
     1648         * @param int $inviter_id ID of the inviter.
    15501649         */
    1551         do_action( 'groups_delete_invite', $user_id, $group_id );
     1650        do_action( 'groups_delete_invite', $user_id, $group_id, $inviter_id );
    15521651
    15531652        return true;
    15541653}
    15551654
    15561655/**
    1557  * Send all pending invites by a single user to a specific group.
     1656 * Send some or all pending invites by a single user to a specific group.
    15581657 *
    15591658 * @since 1.0.0
     1659 * @since 5.0.0 Parameters changed to associative array.
    15601660 *
    1561  * @param int $user_id  ID of the inviting user.
    1562  * @param int $group_id ID of the group.
     1661 * @param array $args {
     1662 *     An array of optional arguments.
     1663 *     @type int    $user_id       ID of the invited user.
     1664 *     @type string $invitee_email Email address of the invited user, if not a member of the site.
     1665 *     @type string $group_id      ID of the group or an array of group IDs.
     1666 *     @type string $inviter_id    ID of the user extending the invitation.
     1667 *     @type bool   $force_resend  Whether to resend the email & notification if one has already been sent.
     1668 * }
    15631669 */
    1564 function groups_send_invites( $user_id, $group_id ) {
     1670function groups_send_invites( $args = array() ) {
     1671        // Backward compatibility with old method of passing arguments.
     1672        if ( ! is_array( $args ) || func_num_args() > 1 ) {
     1673                _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__ ) );
    15651674
    1566         if ( empty( $user_id ) )
    1567                 $user_id = bp_loggedin_user_id();
     1675                $old_args_keys = array(
     1676                        0 => 'inviter_id',
     1677                        1 => 'group_id',
     1678                );
    15681679
    1569         // Send friend invites.
    1570         $invited_users = groups_get_invites_for_group( $user_id, $group_id );
    1571         $group = groups_get_group( $group_id );
     1680                $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
     1681        }
    15721682
    1573         for ( $i = 0, $count = count( $invited_users ); $i < $count; ++$i ) {
    1574                 $member = new BP_Groups_Member( $invited_users[$i], $group_id );
     1683        $r = bp_parse_args( $args, array(
     1684                'user_id'       => false,
     1685                'invitee_email' => '',
     1686                'group_id'      => 0,
     1687                'inviter_id'    => bp_loggedin_user_id(),
     1688                'force_resend'  => false,
     1689        ), 'groups_send_invitation' );
    15751690
    1576                 // Skip if we've already sent an invite to this user.
    1577                 if ( $member->invite_sent ) {
    1578                         continue;
    1579                 }
     1691        /*
     1692         * We will generally only want to fetch unsent invitations.
     1693         * If force_resend is true, then we need to fetch both sent and draft invites.
     1694         */
     1695        if ( $r['force_resend'] ) {
     1696                $args['invite_sent'] = 'all';
     1697        } else {
     1698                $args['invite_sent'] = 'draft';
     1699        }
    15801700
    1581                 // Send the actual invite.
    1582                 groups_notification_group_invites( $group, $member, $user_id );
     1701        $args = array(
     1702                'user_id'       => $r['user_id'],
     1703                'invitee_email' => $r['invitee_email'],
     1704                'item_id'       => $r['group_id'],
     1705                'inviter_id'    => $r['inviter_id'],
     1706        );
     1707        $invites = groups_get_invites( $args );
    15831708
    1584                 $member->invite_sent = 1;
    1585                 $member->save();
     1709        $invited_users = array();
     1710
     1711        $invites_class = new BP_Groups_Invitation_Manager();
     1712        foreach ( $invites as $invite ) {
     1713                $invited_users[] = $invite->user_id;
     1714                $invites_class->send_invitation_by_id( $invite->id );
    15861715        }
    15871716
    15881717        /**
    function groups_send_invites( $user_id, $group_id ) { 
    15951724         * @param array $invited_users Array of users being invited to the group.
    15961725         * @param int   $user_id       ID of the inviting user.
    15971726         */
    1598         do_action( 'groups_send_invites', $group_id, $invited_users, $user_id );
     1727        do_action( 'groups_send_invites', $r['group_id'], $invited_users, $r['inviter_id'] );
    15991728}
    16001729
    16011730/**
    1602  * Get IDs of users with outstanding invites to a given group from a specified user.
     1731 * Get IDs of users with outstanding invites to a given group.
    16031732 *
    16041733 * @since 1.0.0
    16051734 * @since 2.9.0 Added $sent as a parameter.
    function groups_get_invites_for_group( $user_id, $group_id, $sent = null ) { 
    16171746        return BP_Groups_Group::get_invites( $user_id, $group_id, $sent );
    16181747}
    16191748
     1749/**
     1750 * Get invitations to a given group filtered by arguments.
     1751 *
     1752 * @since 5.0.0
     1753 *
     1754 * @param int   $group_id ID of the group.
     1755 * @param array $args     Invitation arguments.
     1756 *                        See BP_Invitation::get() for list.
     1757 *
     1758 * @return array $invites     Matching BP_Invitation objects.
     1759 */
     1760function groups_get_invites( $args = array() ) {
     1761        $invites_class = new BP_Groups_Invitation_Manager();
     1762        return $invites_class->get_invitations( $args );
     1763}
     1764
    16201765/**
    16211766 * Check to see whether a user has already been invited to a group.
    16221767 *
    function groups_get_invites_for_group( $user_id, $group_id, $sent = null ) { 
    16301775 * @param int    $group_id ID of potential group.
    16311776 * @param string $type     Optional. Use 'sent' to check for sent invites,
    16321777 *                         'all' to check for all. Default: 'sent'.
    1633  * @return int|bool ID of the membership if found, otherwise false.
     1778 * @return int|bool ID of the first found membership if found, otherwise false.
    16341779 */
    16351780function groups_check_user_has_invite( $user_id, $group_id, $type = 'sent' ) {
    1636         $invite = false;
     1781        return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
     1782}
     1783
     1784/**
     1785 * Check to see whether a user has already been invited to a group by a particular user.
     1786 *
     1787 * By default, the function checks for invitations that have been sent.
     1788 * Entering 'all' as the $type parameter will return unsent invitations as
     1789 * well (useful to make sure AJAX requests are not duplicated).
     1790 *
     1791 * @since 5.0.0
     1792 *
     1793 * @param int    $user_id    ID of potential group member.
     1794 * @param int    $group_id   ID of potential group.
     1795 * @param string $inviter_id Optional. Use 'sent' to check for sent invites,
     1796 *                           'all' to check for all. Default: 'sent'.
     1797 * @param string $type       Optional. Specify a user ID to limit to only invited from that user.
     1798 *                           Default: 'false'.
     1799 * @return int|bool ID of the first found membership if found, otherwise false.
     1800 */
     1801 function groups_check_has_invite_from_user( $user_id, $group_id, $inviter_id = false, $type = 'sent' ) {
     1802        if ( empty( $user_id ) || empty( $group_id ) ) {
     1803                return false;
     1804        }
    16371805
    16381806        $args = array(
    1639                 'is_confirmed' => false,
    1640                 'is_banned'    => null,
    1641                 'is_admin'     => null,
    1642                 'is_mod'       => null,
     1807                'user_id'     => $user_id,
     1808                'item_id'     => $group_id,
     1809                'invite_sent' => 'sent',
    16431810        );
    1644 
    1645         if ( 'sent' === $type ) {
    1646                 $args['invite_sent'] = true;
     1811        if ( $inviter_id ) {
     1812                $args['inviter_id'] = $inviter_id;
    16471813        }
    1648 
    1649         $user_groups = bp_get_user_groups( $user_id, $args );
    1650 
    1651         if ( isset( $user_groups[ $group_id ] ) && 0 !== $user_groups[ $group_id ]->inviter_id ) {
    1652                 $invite = $user_groups[ $group_id ]->id;
     1814        if ( $type === 'draft' || $type === 'all' ) {
     1815                $args['invite_sent'] = $type;
    16531816        }
    16541817
    1655         return $invite;
     1818        $invites_class = new BP_Groups_Invitation_Manager();
     1819
     1820        return $invites_class->invitation_exists( $args );
    16561821}
    16571822
    16581823/**
    function groups_remove_member( $user_id, $group_id ) { 
    18291994 *
    18301995 * @since 1.0.0
    18311996 *
    1832  * @param int $requesting_user_id ID of the user requesting membership.
    1833  * @param int $group_id           ID of the group.
     1997 * @param array|string $args {
     1998 *     Array of arguments.
     1999 *     @type int    $user_id       ID of the user being invited.
     2000 *     @type int    $group_id      ID of the group to which the user is being invited.
     2001 *     @type string $content       Optional. Message to invitee.
     2002 *     @type string $date_modified Optional. Modified date for the invitation.
     2003 *                                 Default: current date/time.
     2004 * }
    18342005 * @return bool True on success, false on failure.
    18352006 */
    1836 function groups_send_membership_request( $requesting_user_id, $group_id ) {
    1837 
    1838         // Prevent duplicate requests.
    1839         if ( groups_check_for_membership_request( $requesting_user_id, $group_id ) )
    1840                 return false;
     2007function groups_send_membership_request( $args = array() ) {
     2008        // Backward compatibility with old method of passing arguments.
     2009        if ( ! is_array( $args ) || func_num_args() > 1 ) {
     2010                _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__ ) );
    18412011
    1842         // Check if the user is already a member or is banned.
    1843         if ( groups_is_user_member( $requesting_user_id, $group_id ) || groups_is_user_banned( $requesting_user_id, $group_id ) )
    1844                 return false;
     2012                $old_args_keys = array(
     2013                        0 => 'user_id',
     2014                        1 => 'group_id',
     2015                );
    18452016
    1846         // Check if the user is already invited - if so, simply accept invite.
    1847         if ( groups_check_user_has_invite( $requesting_user_id, $group_id ) ) {
    1848                 groups_accept_invite( $requesting_user_id, $group_id );
    1849                 return true;
     2017                $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
    18502018        }
    18512019
    1852         $requesting_user                = new BP_Groups_Member;
    1853         $requesting_user->group_id      = $group_id;
    1854         $requesting_user->user_id       = $requesting_user_id;
    1855         $requesting_user->inviter_id    = 0;
    1856         $requesting_user->is_admin      = 0;
    1857         $requesting_user->user_title    = '';
    1858         $requesting_user->date_modified = bp_core_current_time();
    1859         $requesting_user->is_confirmed  = 0;
    1860         $requesting_user->comments      = isset( $_POST['group-request-membership-comments'] ) ? $_POST['group-request-membership-comments'] : '';
     2020        $r = bp_parse_args( $args, array(
     2021                'user_id'       => false,
     2022                'group_id'      => false,
     2023                'content'       => '',
     2024                'date_modified' => bp_core_current_time(),
     2025        ), 'groups_send_membership_request' );
     2026
     2027        $inv_args = array(
     2028                'user_id'       => $r['user_id'],
     2029                'item_id'       => $r['group_id'],
     2030                'content'       => $r['content'],
     2031                'date_modified' => $r['date_modified'],
     2032        );
    18612033
    1862         if ( $requesting_user->save() ) {
    1863                 $admins = groups_get_group_admins( $group_id );
     2034        $invites_class = new BP_Groups_Invitation_Manager();
     2035        $request_id = $invites_class->add_request( $inv_args );
    18642036
    1865                 // Saved okay, now send the email notification.
    1866                 for ( $i = 0, $count = count( $admins ); $i < $count; ++$i )
    1867                         groups_notification_new_membership_request( $requesting_user_id, $admins[$i]->user_id, $group_id, $requesting_user->id );
     2037        // If a new request was created, send the emails.
     2038        if ( $request_id && is_int( $request_id ) ) {
     2039                $invites_class->send_request_notification_by_id( $request_id );
     2040                $admins = groups_get_group_admins( $r['group_id'] );
    18682041
    18692042                /**
    18702043                 * Fires after the creation of a new membership request.
    function groups_send_membership_request( $requesting_user_id, $group_id ) { 
    18742047                 * @param int   $requesting_user_id  ID of the user requesting membership.
    18752048                 * @param array $admins              Array of group admins.
    18762049                 * @param int   $group_id            ID of the group being requested to.
    1877                  * @param int   $requesting_user->id ID of the membership.
     2050                 * @param int   $request_id          ID of the request.
    18782051                 */
    1879                 do_action( 'groups_membership_requested', $requesting_user_id, $admins, $group_id, $requesting_user->id );
     2052                do_action( 'groups_membership_requested', $r['user_id'], $admins, $r['group_id'], $request_id );
    18802053
    1881                 return true;
     2054                return $request_id;
    18822055        }
    18832056
    18842057        return false;
    function groups_send_membership_request( $requesting_user_id, $group_id ) { 
    18882061 * Accept a pending group membership request.
    18892062 *
    18902063 * @since 1.0.0
     2064 * @since 5.0.0 Deprecated $membership_id argument.
    18912065 *
    1892  * @param int $membership_id ID of the membership object.
    1893  * @param int $user_id       Optional. ID of the user who requested membership.
     2066 * @param int $membership_id Deprecated 5.0.0.
     2067 * @param int $user_id       Required. ID of the user who requested membership.
    18942068 *                           Provide this value along with $group_id to override
    18952069 *                           $membership_id.
    1896  * @param int $group_id      Optional. ID of the group to which membership is being
     2070 * @param int $group_id      Required. ID of the group to which membership is being
    18972071 *                           requested. Provide this value along with $user_id to
    18982072 *                           override $membership_id.
    18992073 * @return bool True on success, false on failure.
    19002074 */
    19012075function groups_accept_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    19022076
    1903         if ( !empty( $user_id ) && !empty( $group_id ) ) {
    1904                 $membership = new BP_Groups_Member( $user_id, $group_id );
    1905         } else {
    1906                 $membership = new BP_Groups_Member( false, false, $membership_id );
     2077        if ( ! empty( $membership_id ) ) {
     2078                _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__ ) );
    19072079        }
    19082080
    1909         $membership->accept_request();
    1910 
    1911         if ( !$membership->save() ) {
     2081        if ( ! $user_id || ! $group_id ) {
    19122082                return false;
    19132083        }
    19142084
    1915         // Check if the user has an outstanding invite, if so delete it.
    1916         if ( groups_check_user_has_invite( $membership->user_id, $membership->group_id ) ) {
    1917                 groups_delete_invite( $membership->user_id, $membership->group_id );
    1918         }
    1919 
    1920         /**
    1921          * Fires after a group membership request has been accepted.
    1922          *
    1923          * @since 1.0.0
    1924          *
    1925          * @param int  $user_id  ID of the user who accepted membership.
    1926          * @param int  $group_id ID of the group that was accepted membership to.
    1927          * @param bool $value    If membership was accepted.
    1928          */
    1929         do_action( 'groups_membership_accepted', $membership->user_id, $membership->group_id, true );
     2085        $invites_class = new BP_Groups_Invitation_Manager();
     2086        $args = array(
     2087                'user_id' => $user_id,
     2088                'item_id' => $group_id,
     2089        );
    19302090
    1931         return true;
     2091        return $invites_class->accept_request( $args );
    19322092}
    19332093
    19342094/**
    function groups_accept_membership_request( $membership_id, $user_id = 0, $group_ 
    19362096 *
    19372097 * @since 1.0.0
    19382098 *
    1939  * @param int $membership_id ID of the membership object.
     2099 * @param int $membership_id Deprecated 5.0.0.
    19402100 * @param int $user_id       Optional. ID of the user who requested membership.
    19412101 *                           Provide this value along with $group_id to override
    19422102 *                           $membership_id.
    function groups_accept_membership_request( $membership_id, $user_id = 0, $group_ 
    19462106 * @return bool True on success, false on failure.
    19472107 */
    19482108function groups_reject_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    1949         if ( !$membership = groups_delete_membership_request( $membership_id, $user_id, $group_id ) ) {
     2109
     2110        if ( ! empty( $membership_id ) ){
     2111                _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__ ) );
     2112        }
     2113
     2114        if ( ! groups_delete_membership_request( false, $user_id, $group_id ) ) {
    19502115                return false;
    19512116        }
    19522117
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    19592124         * @param int  $group_id ID of the group that was rejected membership to.
    19602125         * @param bool $value    If membership was accepted.
    19612126         */
    1962         do_action( 'groups_membership_rejected', $membership->user_id, $membership->group_id, false );
     2127        do_action( 'groups_membership_rejected', $user_id, $group_id, false );
    19632128
    19642129        return true;
    19652130}
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    19692134 *
    19702135 * @since 1.2.0
    19712136 *
    1972  * @param int $membership_id ID of the membership object.
     2137 * @param int $membership_id Deprecated 5.0.0.
    19732138 * @param int $user_id       Optional. ID of the user who requested membership.
    19742139 *                           Provide this value along with $group_id to override
    19752140 *                           $membership_id.
    function groups_reject_membership_request( $membership_id, $user_id = 0, $group_ 
    19792144 * @return false|BP_Groups_Member True on success, false on failure.
    19802145 */
    19812146function groups_delete_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
    1982         if ( !empty( $user_id ) && !empty( $group_id ) )
    1983                 $membership = new BP_Groups_Member( $user_id, $group_id );
    1984         else
    1985                 $membership = new BP_Groups_Member( false, false, $membership_id );
     2147        if ( ! empty( $membership_id ) ){
     2148                _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__ ) );
     2149        }
    19862150
    1987         if ( ! BP_Groups_Member::delete_request( $membership->user_id, $membership->group_id ) )
     2151        if ( empty( $user_id ) || empty( $group_id ) ) {
    19882152                return false;
     2153        }
     2154
     2155        $invites_class = new BP_Groups_Invitation_Manager();
     2156        $success       = $invites_class->delete_requests( array(
     2157                'user_id' => $user_id,
     2158                'item_id' => $group_id
     2159        ) );
     2160
     2161        return $success;
     2162}
    19892163
    1990         return $membership;
     2164/**
     2165 * Get group membership requests filtered by arguments.
     2166 *
     2167 * @since 5.0.0
     2168 *
     2169 * @param int   $group_id ID of the group.
     2170 * @param array $args     Invitation arguments.
     2171 *                        See BP_Invitation::get() for list.
     2172 *
     2173 * @return array $requests Matching BP_Invitation objects.
     2174 */
     2175function groups_get_requests( $args = array() ) {
     2176        $invites_class = new BP_Groups_Invitation_Manager();
     2177        return $invites_class->get_requests( $args );
    19912178}
    19922179
    19932180/**
    function groups_delete_membership_request( $membership_id, $user_id = 0, $group_ 
    19972184 *
    19982185 * @param int $user_id  ID of the user.
    19992186 * @param int $group_id ID of the group.
    2000  * @return int|bool ID of the membership if found, otherwise false.
     2187 * @return int|bool ID of the request if found, otherwise false.
    20012188 */
    20022189function groups_check_for_membership_request( $user_id, $group_id ) {
    2003         $request = false;
     2190        if ( empty( $user_id ) || empty( $group_id ) ) {
     2191                return false;
     2192        }
    20042193
    2005         $user_groups = bp_get_user_groups( $user_id, array(
    2006                 'is_confirmed' => false,
    2007                 'is_banned'    => false,
    2008                 'is_admin'     => null,
    2009                 'is_mod'       => null
     2194        $args = array(
     2195                'user_id' => $user_id,
     2196                'item_id' => $group_id,
     2197        );
     2198        $invites_class = new BP_Groups_Invitation_Manager();
     2199
     2200        return $invites_class->request_exists( $args );
     2201}
     2202
     2203 /**
     2204  * Get an array of group IDs to which a user has requested membership.
     2205  *
     2206  * @since 5.0.0
     2207  *
     2208  * @param int $user_id The user ID.
     2209  *
     2210  * @return array Array of group IDs.
     2211  */
     2212 function groups_get_membership_requested_group_ids( $user_id = 0 ) {
     2213        if ( ! $user_id ) {
     2214                $user_id = bp_loggedin_user_id();
     2215        }
     2216
     2217        $group_ids     = groups_get_requests( array(
     2218                'user_id' => $user_id,
     2219                'fields'  => 'item_ids'
    20102220        ) );
    20112221
    2012         if ( isset( $user_groups[ $group_id ] ) && 0 === $user_groups[ $group_id ]->inviter_id ) {
    2013                 $request = $user_groups[ $group_id ]->id;
     2222        return $group_ids;
     2223}
     2224
     2225 /**
     2226  * Get an array of group IDs to which a user has requested membership.
     2227  *
     2228  * @since 5.0.0
     2229  *
     2230  * @param int $user_id The user ID.
     2231  *
     2232  * @return array Array of group IDs.
     2233  */
     2234 function groups_get_membership_requested_user_ids( $group_id = 0 ) {
     2235        if ( ! $group_id ) {
     2236                $group_id = bp_get_current_group_id();
    20142237        }
    20152238
    2016         return $request;
     2239        $requests = groups_get_requests( array(
     2240                'item_id' => $group_id,
     2241                'fields'  => 'user_ids'
     2242        ) );
     2243
     2244        return $requests;
    20172245}
    20182246
    20192247/**
    function groups_check_for_membership_request( $user_id, $group_id ) { 
    20242252 * @param int $group_id ID of the group.
    20252253 * @return bool True on success, false on failure.
    20262254 */
    2027 function groups_accept_all_pending_membership_requests( $group_id ) {
    2028         $user_ids = BP_Groups_Member::get_all_membership_request_user_ids( $group_id );
     2255function groups_accept_all_pending_membership_requests( $group_id = 0 ) {
     2256        if ( ! $group_id ) {
     2257                $group_id = bp_get_current_group_id();
     2258        }
     2259
     2260        $user_ids = groups_get_membership_requested_user_ids( $group_id );
    20292261
    2030         if ( !$user_ids )
     2262        if ( ! $user_ids ) {
    20312263                return false;
     2264        }
    20322265
    2033         foreach ( (array) $user_ids as $user_id )
     2266        foreach ( (array) $user_ids as $user_id ) {
    20342267                groups_accept_membership_request( false, $user_id, $group_id );
     2268        }
    20352269
    20362270        /**
    20372271         * Fires after the acceptance of all pending membership requests to a group.
    function bp_groups_pending_requests_personal_data_exporter( $email_address, $pag 
    27072941                );
    27082942        }
    27092943
    2710         $requests = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2711                 'type'     => 'pending_request',
     2944        $requests = groups_get_requests( array(
     2945                'user_id'  => $user->ID,
    27122946                'page'     => $page,
    27132947                'per_page' => $number,
    27142948        ) );
    27152949
    27162950        foreach ( $requests as $request ) {
    2717                 $group = groups_get_group( $request->group_id );
     2951                $group = groups_get_group( $request->item_id );
    27182952
    27192953                $item_data = array(
    27202954                        array(
    function bp_groups_pending_sent_invitations_personal_data_exporter( $email_addre 
    27733007                );
    27743008        }
    27753009
    2776         $invitations = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2777                 'type'     => 'pending_sent_invitation',
    2778                 'page'     => $page,
    2779                 'per_page' => $number,
     3010        $invitations = groups_get_invites( array(
     3011                'inviter_id'  => $user->ID,
     3012                'page'        => $page,
     3013                'per_page'    => $number,
    27803014        ) );
    27813015
    27823016        foreach ( $invitations as $invitation ) {
    2783                 $group = groups_get_group( $invitation->group_id );
     3017                $group = groups_get_group( $invitation->item_id );
    27843018
    27853019                $item_data = array(
    27863020                        array(
    function bp_groups_pending_received_invitations_personal_data_exporter( $email_a 
    28433077                );
    28443078        }
    28453079
    2846         $invitations = BP_Groups_Member::get_user_memberships( $user->ID, array(
    2847                 'type'     => 'pending_received_invitation',
     3080        $invitations = groups_get_invites( array(
     3081                'user_id'  => $user->ID,
    28483082                'page'     => $page,
    28493083                'per_page' => $number,
    28503084        ) );
    28513085
    28523086        foreach ( $invitations as $invitation ) {
    2853                 $group = groups_get_group( $invitation->group_id );
     3087                $group = groups_get_group( $invitation->item_id );
    28543088
    28553089                $item_data = array(
    28563090                        array(
    function bp_groups_pending_received_invitations_personal_data_exporter( $email_a 
    28873121                'done' => $done,
    28883122        );
    28893123}
     3124
     3125/**
     3126 * Migrate invitations and requests from pre-5.0 group_members table to invitations table.
     3127 *
     3128 * @since 5.0.0
     3129 */
     3130function bp_groups_migrate_invitations() {
     3131        global $wpdb;
     3132        $bp = buddypress();
     3133
     3134        $records = $wpdb->get_results( "SELECT id, group_id, user_id, inviter_id, date_modified, comments, invite_sent FROM {$bp->groups->table_name_members} WHERE is_confirmed = 0 AND is_banned = 0" );
     3135
     3136        $processed = array();
     3137        foreach ( $records as $record ) {
     3138                $invitation = new BP_Invitation;
     3139                $invitation->user_id           = $record->user_id;
     3140                $invitation->inviter_id        = $record->inviter_id;
     3141                $invitation->invitee_email     = '';
     3142                $invitation->class             = 'BP_Groups_Invitation_Manager';
     3143                $invitation->item_id           = $record->group_id;
     3144                $invitation->secondary_item_id = 0;
     3145                $invitation->type              = ( 0 === (int) $record->inviter_id ) ? 'request' : 'invite';
     3146                $invitation->content           = $record->comments;
     3147                $invitation->date_modified     = $record->date_modified;
     3148                $invitation->invite_sent       = $record->invite_sent;
     3149                $invitation->accepted          = 0;
     3150
     3151                $invite_id = $invitation->save();
     3152                $processed[] = (int) $record->id;
     3153        }
     3154
     3155        $ids_to_delete = implode( ',', $processed );
     3156        if ( $ids_to_delete ) {
     3157                $wpdb->query( "DELETE FROM {$bp->groups->table_name_members} WHERE ID IN ($ids_to_delete)" );
     3158        }
     3159}
  • 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 d4d59ab2d..3ccfd2a22 100644
    function bp_group_request_reject_link() { 
    54865486        function bp_get_group_request_reject_link() {
    54875487                global $requests_template;
    54885488
     5489                $link = add_query_arg( array(
     5490                        '_wpnonce' => wp_create_nonce( 'groups_reject_membership_request' ),
     5491                        'user_id'  => $requests_template->request->user_id,
     5492                        'action'   => 'reject'
     5493                ), trailingslashit( bp_get_group_permalink( groups_get_current_group() ) ) . 'admin/membership-requests/' );
     5494
    54895495                /**
    54905496                 * Filters the URL to use to reject a membership request.
    54915497                 *
    function bp_group_request_reject_link() { 
    54935499                 *
    54945500                 * @param string $value URL to use to reject a membership request.
    54955501                 */
    5496                 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' ) );
     5502                return apply_filters( 'bp_get_group_request_reject_link', $link );
    54975503        }
    54985504
    54995505/**
    function bp_group_request_accept_link() { 
    55105516        function bp_get_group_request_accept_link() {
    55115517                global $requests_template;
    55125518
     5519                $link = add_query_arg( array(
     5520                        '_wpnonce' => wp_create_nonce( 'groups_accept_membership_request' ),
     5521                        'user_id'  => $requests_template->request->user_id,
     5522                        'action'   => 'accept'
     5523                ), trailingslashit( bp_get_group_permalink( groups_get_current_group() ) ) . 'admin/membership-requests/' );
     5524
    55135525                /**
    55145526                 * Filters the URL to use to accept a membership request.
    55155527                 *
    function bp_group_request_accept_link() { 
    55175529                 *
    55185530                 * @param string $value URL to use to accept a membership request.
    55195531                 */
    5520                 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' ) );
     5532                return apply_filters( 'bp_get_group_request_accept_link', $link );
    55215533        }
    55225534
    55235535/**
  • 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..dca139318 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;
     970                }
     971                if ( $page ) {
     972                        $args['page'] = $page;
    966973                }
    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_Invitation_Manager();
    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-invitation-manager.php

    diff --git src/bp-groups/classes/class-bp-groups-invitation-manager.php src/bp-groups/classes/class-bp-groups-invitation-manager.php
    new file mode 100644
    index 000000000..d22cd0977
    - +  
     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_Invitation_Manager extends BP_Invitation_Manager {
     22        /**
     23         * Construct parameters.
     24         *
     25         * @since 5.0.0
     26         *
     27         * @param array|string $args.
     28         */
     29        public function __construct( $args = '' ) {
     30                parent::__construct();
     31        }
     32
     33        /**
     34         * This is where custom actions are added to run when notifications of an
     35         * invitation or request need to be generated & sent.
     36         *
     37         * @since 5.0.0
     38         *
     39         * @param int $id The ID of the invitation to mark as sent.
     40         * @return bool True on success, false on failure.
     41         */
     42        public function run_send_action( BP_Invitation $invitation ) {
     43                // Notify group admins of the pending request
     44                if ( 'request' === $invitation->type ) {
     45                        $admins = groups_get_group_admins( $invitation->item_id );
     46
     47                        foreach ( $admins as $admin ) {
     48                                groups_notification_new_membership_request( $invitation->user_id, $admin->user_id, $invitation->item_id, $invitation->id );
     49                        }
     50                        return true;
     51
     52                // Notify the invitee of the invitation.
     53                } else {
     54                        $group = groups_get_group( $invitation->item_id );
     55                        groups_notification_group_invites( $group, $invitation->user_id, $invitation->inviter_id );
     56                        return true;
     57                }
     58        }
     59
     60        /**
     61         * This is where custom actions are added to run when an invitation
     62         * or request is accepted.
     63         *
     64         * @since 5.0.0
     65         *
     66         * @param string $type Are we accepting an invitation or request?
     67         * @param array  $r    Parameters that describe the invitation being accepted.
     68         * @return bool True on success, false on failure.
     69         */
     70        public function run_acceptance_action( $type = 'invite', $r  ) {
     71                // If the user is already a member (because BP at one point allowed two invitations to
     72                // slip through), return early.
     73                if ( groups_is_user_member( $r['user_id'], $r['item_id'] ) ) {
     74                        return true;
     75                }
     76
     77                // Create the new membership
     78                $member = new BP_Groups_Member( $r['user_id'], $r['item_id'] );
     79
     80                if ( 'request' === $type ) {
     81                        $member->accept_request();
     82                } else {
     83                        $member->accept_invite();
     84                }
     85
     86                if ( ! $member->save() ) {
     87                        return false;
     88                }
     89
     90                if ( 'request' === $type ) {
     91                        /**
     92                         * Fires after a group membership request has been accepted.
     93                         *
     94                         * @since 1.0.0
     95                         *
     96                         * @param int  $user_id  ID of the user who accepted membership.
     97                         * @param int  $group_id ID of the group that was accepted membership to.
     98                         * @param bool $value    If membership was accepted.
     99                         */
     100                        do_action( 'groups_membership_accepted', $r['user_id'], $r['item_id'], true );
     101                } else {
     102                        // Get an inviter_id from the invitation.
     103                        $invites = groups_get_invites( $r );
     104                        $inviter_id = 0;
     105                        if ( $invites ) {
     106                                $inviter_id = current( $invites )->inviter_id;
     107                        }
     108
     109                        /**
     110                         * Fires after a user has accepted a group invite.
     111                         *
     112                         * @since 1.0.0
     113                         * @since 2.8.0 The $inviter_id arg was added.
     114                         *
     115                         * @param int $user_id    ID of the user who accepted the group invite.
     116                         * @param int $group_id   ID of the group being accepted to.
     117                         * @param int $inviter_id ID of the user who invited this user to the group.
     118                         */
     119                        do_action( 'groups_accept_invite', $r['user_id'], $r['item_id'], $inviter_id );
     120                }
     121
     122                // Modify group meta.
     123                groups_update_groupmeta( $r['item_id'], 'last_activity', bp_core_current_time() );
     124
     125                return true;
     126        }
     127
     128        /**
     129         * With group invitations, we don't need to keep the old record, so we delete rather than
     130         * mark invitations as "accepted."
     131         *
     132         * @since 5.0.0
     133         *
     134         * @see BP_Invitation::mark_accepted_by_data()
     135         *      for a description of arguments.
     136         *
     137         * @param array $args.
     138         */
     139        public function mark_accepted( $args ) {
     140                // Delete all existing invitations/requests to this group for this user.
     141                $this->delete( array(
     142                        'user_id' => $args['user_id'],
     143                        'item_id' => $args['item_id'],
     144                        'type'    => 'all'
     145                ) );
     146        }
     147
     148        /**
     149         * Should this invitation be created?
     150         *
     151         * @since 5.0.0
     152         *
     153         * @param array $args.
     154         * @return bool
     155         */
     156        public function allow_invitation( $args ) {
     157                // Does the inviter have this capability?
     158                if ( ! bp_user_can( $args['inviter_id'], 'groups_send_invitation', array( 'group_id' => $args['item_id'] ) ) ) {
     159                        return false;
     160                }
     161
     162                // Is the invited user eligible to receive an invitation?
     163                if ( ! bp_user_can( $args['user_id'], 'groups_receive_invitation', array( 'group_id' => $args['item_id'] ) ) ) {
     164                        return false;
     165                }
     166
     167                // Prevent duplicated invitations.
     168                if ( groups_check_has_invite_from_user( $args['user_id'], $args['item_id'], $args['inviter_id'], 'all' ) ) {
     169                        return false;
     170                }
     171
     172                return true;
     173        }
     174
     175        /**
     176         * Should this request be created?
     177         *
     178         * @since 5.0.0
     179         *
     180         * @param array $args.
     181         * @return bool.
     182         */
     183        public function allow_request( $args ) {
     184                // Does the requester have this capability? (Also checks for duplicates.)
     185                if ( ! bp_user_can( $args['user_id'], 'groups_request_membership', array( 'group_id' => $args['item_id'] ) ) ) {
     186                        return false;
     187                }
     188
     189                return true;
     190        }
     191}
  • 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..a442ce932 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 { 
    862836
    863837                switch ( $r['type'] ) {
    864838                        case 'pending_request' :
    865                                 $sql['where'] = $wpdb->prepare( "user_id = %d AND is_confirmed = 0 AND inviter_id = 0", $user_id );
     839                                return groups_get_requests( array(
     840                                        'user_id'  => $user_id,
     841                                        'page'     => $r['page'],
     842                                        'per_page' => $r['per_page'],
     843                                ) );
    866844                        break;
    867845
    868846                        case 'pending_received_invitation' :
    869                                 $sql['where'] = $wpdb->prepare( "user_id = %d AND is_confirmed = 0 AND inviter_id != 0", $user_id );
     847                                return groups_get_invites( array(
     848                                        'user_id'  => $user_id,
     849                                        'page'     => $r['page'],
     850                                        'per_page' => $r['per_page'],
     851                                ) );
    870852                        break;
    871853
    872854                        case 'pending_sent_invitation' :
    873                                 $sql['where'] = $wpdb->prepare( "inviter_id = %d AND is_confirmed = 0", $user_id );
     855                                return groups_get_invites( array(
     856                                        'inviter_id'  => $user_id,
     857                                        'page'        => $r['page'],
     858                                        'per_page'    => $r['per_page'],
     859                                ) );
    874860                        break;
    875861
    876862                        case 'membership' :
    class BP_Groups_Member { 
    912898         * @return int|null The ID of the invitation if found; null if not found.
    913899         */
    914900        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;
     901                return groups_is_user_invited( $user_id, $group_id, $type );
    929902        }
    930903
    931904        /**
    class BP_Groups_Member { 
    935908         *
    936909         * @global WPDB $wpdb
    937910         *
    938          * @param  int $user_id  ID of the user.
    939          * @param  int $group_id ID of the group.
     911         * @param  int $user_id    ID of the user.
     912         * @param  int $group_id   ID of the group.
     913         * @param  int $inviter_id ID of the inviter. Specify if you want to delete
     914         *                         a specific invite. Leave false if you want to
     915         *                         delete all invites to this group.
    940916         * @return int Number of records deleted.
    941917         */
    942         public static function delete_invite( $user_id, $group_id ) {
    943                 global $wpdb;
    944 
    945                 if ( empty( $user_id ) ) {
    946                         return false;
    947                 }
    948 
     918        public static function delete_invite( $user_id, $group_id, $inviter_id = false ) {
    949919                /**
    950920                 * Fires before a group invitation is deleted.
    951921                 *
    952922                 * @since 2.6.0
     923                 * @since 5.0.0 Added $inviter_id
    953924                 *
    954925                 * @param int $user_id  ID of the user.
    955926                 * @param int $group_id ID of the group.
     927                 * @param  int $inviter_id ID of the inviter.
    956928                 */
    957                 do_action( 'bp_groups_member_before_delete_invite', $user_id, $group_id );
    958 
    959                 $table_name = buddypress()->groups->table_name_members;
     929                do_action( 'bp_groups_member_before_delete_invite', $user_id, $group_id, $inviter_id );
    960930
    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 );
    968 
    969                 return $wpdb->query( $prepared );
     931                return groups_delete_invite( $user_id, $group_id, $inviter_id );
    970932        }
    971933
    972934        /**
    class BP_Groups_Member { 
    979941         * @return int Number of records deleted.
    980942         */
    981943        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 ) );
     944                return groups_delete_membership_request( false, $user_id, $group_id );
    990945        }
    991946
    992947        /**
    class BP_Groups_Member { 
    11041059         * @return int Database ID of the membership if found; int 0 on failure.
    11051060         */
    11061061        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 ) );
     1062                return groups_is_user_pending( $user_id, $group_id );
    11151063        }
    11161064
    11171065        /**
    class BP_Groups_Member { 
    12921240         * @return array IDs of users with outstanding membership requests.
    12931241         */
    12941242        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 ) ) );
     1243                return groups_get_membership_requested_user_ids( $group_id );
    13001244        }
    13011245
    13021246        /**
  • 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..2b99f4f03 100644
    function groups_screen_group_admin_requests() { 
    2323                return false;
    2424        }
    2525
    26         $request_action = (string) bp_action_variable( 1 );
    27         $membership_id  = (int) bp_action_variable( 2 );
     26        $request_action = isset( $_GET['action'] ) ? $_GET['action'] : false;
     27        $user_id        = isset( $_GET['user_id'] ) ? (int) $_GET['user_id'] : false;
     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 ( $request_action && $user_id && $group_id ) {
     31                if ( 'accept' === $request_action ) {
    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 ) {
    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/bp-groups/screens/single/send-invites.php

    diff --git src/bp-groups/screens/single/send-invites.php src/bp-groups/screens/single/send-invites.php
    index 3b0365cbe..1e04fee44 100644
    function groups_screen_group_invite() { 
    3131                }
    3232
    3333                // Send the invites.
    34                 groups_send_invites( bp_loggedin_user_id(), $bp->groups->current_group->id );
     34                groups_send_invites( array( 'group_id' => $bp->groups->current_group->id ) );
    3535                bp_core_add_message( __('Group invites sent.', 'buddypress') );
    3636
    3737                /**
    function groups_remove_group_invite() { 
    101101        bp_core_add_message( $message, $error );
    102102        bp_core_redirect( $redirect );
    103103}
    104 add_action( 'bp_screens', 'groups_remove_group_invite' );
    105  No newline at end of file
     104add_action( 'bp_screens', 'groups_remove_group_invite' );
  • src/bp-templates/bp-nouveau/includes/groups/ajax.php

    diff --git src/bp-templates/bp-nouveau/includes/groups/ajax.php src/bp-templates/bp-nouveau/includes/groups/ajax.php
    index 93167c69f..718f1c489 100644
    function bp_nouveau_ajax_send_group_invites() { 
    397397                                array(
    398398                                        'user_id'  => $user_id,
    399399                                        'group_id' => $group_id,
     400                                        'content'  => $_POST['message'],
    400401                                )
    401402                        );
    402403                }
    function bp_nouveau_ajax_send_group_invites() { 
    413414        }
    414415
    415416        // Send the invites.
    416         groups_send_invites( bp_loggedin_user_id(), $group_id );
     417        groups_send_invites( array(     'group_id' => $group_id ) );
    417418
    418419        if ( ! empty( $_POST['message'] ) ) {
    419420                unset( $bp->groups->invites_message );
  • src/bp-templates/bp-nouveau/includes/groups/classes.php

    diff --git src/bp-templates/bp-nouveau/includes/groups/classes.php src/bp-templates/bp-nouveau/includes/groups/classes.php
    index 7d4fe616a..3b68f8003 100644
    class BP_Nouveau_Group_Invite_Query extends BP_User_Query { 
    5050
    5151                $group_member_ids = $this->get_group_member_ids();
    5252
    53                 // We want to get users that are already members of the group
     53                /**
     54                 * We want to exclude users who are already members or who have been
     55                 * invited by **any** of the group members to join it.
     56                 */
    5457                $type = 'exclude';
    5558
    56                 // We want to get invited users who did not confirmed yet
     59                // We want to get the invited users who did not confirmed yet.
    5760                if ( false === $this->query_vars['is_confirmed'] ) {
    5861                        $type = 'include';
    5962                }
    class BP_Nouveau_Group_Invite_Query extends BP_User_Query { 
    7780                        return $this->group_member_ids;
    7881                }
    7982
     83                // Fetch **all** invited users.
     84                $pending_invites = groups_get_invites( array(
     85                        'item_id'     => $this->query_vars['group_id'],
     86                        'invite_sent' => 'sent',
     87                        'fields'      => 'user_ids'
     88                ) );
     89
     90                // This is a clue that we only want the invitations.
     91                if ( false === $this->query_vars['is_confirmed'] ) {
     92                        return $pending_invites;
     93                }
     94
     95                /**
     96                 * Otherwise, we want group members _and_ users with outstanding invitations,
     97                 * because we're doing an "exclude" query.
     98                 */
    8099                $bp  = buddypress();
    81100                $sql = array(
    82101                        'select'  => "SELECT user_id FROM {$bp->groups->table_name_members}",
    class BP_Nouveau_Group_Invite_Query extends BP_User_Query { 
    91110                // Group id
    92111                $sql['where'][] = $wpdb->prepare( 'group_id = %d', $this->query_vars['group_id'] );
    93112
    94                 if ( false === $this->query_vars['is_confirmed'] ) {
    95                         $sql['where'][] = $wpdb->prepare( 'is_confirmed = %d', (int) $this->query_vars['is_confirmed'] );
    96                         $sql['where'][] = 'inviter_id != 0';
    97                 }
    98 
    99113                // Join the query part
    100114                $sql['where'] = ! empty( $sql['where'] ) ? 'WHERE ' . implode( ' AND ', $sql['where'] ) : '';
    101115
    class BP_Nouveau_Group_Invite_Query extends BP_User_Query { 
    106120                /** LIMIT clause ******************************************************/
    107121                $this->group_member_ids = $wpdb->get_col( "{$sql['select']} {$sql['where']} {$sql['orderby']} {$sql['order']} {$sql['limit']}" );
    108122
    109                 return $this->group_member_ids;
     123                return array_merge( $this->group_member_ids, $pending_invites );
    110124        }
    111125
    112126        /**
    class BP_Nouveau_Group_Invite_Query extends BP_User_Query { 
    137151                        return array();
    138152                }
    139153
    140                 $bp = buddypress();
    141 
    142                 return $wpdb->get_col( $wpdb->prepare( "SELECT inviter_id FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id = %d", $user_id, $group_id ) );
     154                return groups_get_invites( array(
     155                        'user_id'     => $user_id,
     156                        'item_id'     => $group_id,
     157                        'invite_sent' => 'sent',
     158                        'fields'      => 'inviter_ids'
     159                ) );
    143160        }
    144161}
    145162
  • src/bp-templates/bp-nouveau/includes/groups/functions.php

    diff --git src/bp-templates/bp-nouveau/includes/groups/functions.php src/bp-templates/bp-nouveau/includes/groups/functions.php
    index 0967ad7c7..46412c6c3 100644
    function bp_nouveau_get_group_potential_invites( $args = array() ) { 
    266266        }
    267267
    268268        // Check the current user's access to the group.
    269         $group = groups_get_group( $r['group_id'] );
    270         if ( ! $group->user_has_access && ! bp_current_user_can( 'bp_moderate' ) ) {
     269        if ( ! bp_groups_user_can_send_invites( $r['group_id'] ) ) {
    271270                return false;
    272271        }
    273272
  • src/class-buddypress.php

    diff --git src/class-buddypress.php src/class-buddypress.php
    index efa9744fc..170893f1e 100644
    class BuddyPress { 
    467467                require( $this->plugin_dir . 'bp-core/bp-core-theme-compatibility.php' );
    468468
    469469                // Require all of the BuddyPress core libraries
    470                 require( $this->plugin_dir . 'bp-core/bp-core-dependency.php'       );
    471                 require( $this->plugin_dir . 'bp-core/bp-core-actions.php'          );
    472                 require( $this->plugin_dir . 'bp-core/bp-core-caps.php'             );
    473                 require( $this->plugin_dir . 'bp-core/bp-core-cache.php'            );
    474                 require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php'            );
    475                 require( $this->plugin_dir . 'bp-core/bp-core-update.php'           );
    476                 require( $this->plugin_dir . 'bp-core/bp-core-options.php'          );
    477                 require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php'         );
    478                 require( $this->plugin_dir . 'bp-core/bp-core-filters.php'          );
    479                 require( $this->plugin_dir . 'bp-core/bp-core-attachments.php'      );
    480                 require( $this->plugin_dir . 'bp-core/bp-core-avatars.php'          );
    481                 require( $this->plugin_dir . 'bp-core/bp-core-widgets.php'          );
    482                 require( $this->plugin_dir . 'bp-core/bp-core-template.php'         );
    483                 require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php'         );
    484                 require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php'         );
    485                 require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php'         );
    486                 require( $this->plugin_dir . 'bp-core/bp-core-functions.php'        );
    487                 require( $this->plugin_dir . 'bp-core/bp-core-moderation.php'       );
    488                 require( $this->plugin_dir . 'bp-core/bp-core-loader.php'           );
    489                 require( $this->plugin_dir . 'bp-core/bp-core-customizer-email.php' );
    490                 require( $this->plugin_dir . 'bp-core/bp-core-rest-api.php'         );
     470                require( $this->plugin_dir . 'bp-core/bp-core-dependency.php'        );
     471                require( $this->plugin_dir . 'bp-core/bp-core-actions.php'           );
     472                require( $this->plugin_dir . 'bp-core/bp-core-caps.php'              );
     473                require( $this->plugin_dir . 'bp-core/bp-core-cache.php'             );
     474                require( $this->plugin_dir . 'bp-core/bp-core-cssjs.php'             );
     475                require( $this->plugin_dir . 'bp-core/bp-core-update.php'            );
     476                require( $this->plugin_dir . 'bp-core/bp-core-options.php'           );
     477                require( $this->plugin_dir . 'bp-core/bp-core-taxonomy.php'          );
     478                require( $this->plugin_dir . 'bp-core/bp-core-filters.php'           );
     479                require( $this->plugin_dir . 'bp-core/bp-core-attachments.php'       );
     480                require( $this->plugin_dir . 'bp-core/bp-core-avatars.php'           );
     481                require( $this->plugin_dir . 'bp-core/bp-core-widgets.php'           );
     482                require( $this->plugin_dir . 'bp-core/bp-core-template.php'          );
     483                require( $this->plugin_dir . 'bp-core/bp-core-adminbar.php'          );
     484                require( $this->plugin_dir . 'bp-core/bp-core-buddybar.php'          );
     485                require( $this->plugin_dir . 'bp-core/bp-core-catchuri.php'          );
     486                require( $this->plugin_dir . 'bp-core/bp-core-functions.php'         );
     487                require( $this->plugin_dir . 'bp-core/bp-core-moderation.php'        );
     488                require( $this->plugin_dir . 'bp-core/bp-core-loader.php'            );
     489                require( $this->plugin_dir . 'bp-core/bp-core-customizer-email.php'  );
     490                require( $this->plugin_dir . 'bp-core/bp-core-rest-api.php'          );
     491                require( $this->plugin_dir . 'bp-core/bp-core-invitations-cache.php' );
    491492
    492493                // Maybe load deprecated functionality (this double negative is proof positive!)
    493494                if ( ! bp_get_option( '_bp_ignore_deprecated_code', ! $this->load_deprecated ) ) {
    class BuddyPress { 
    572573                        'BP_Walker_Category_Checklist' => 'core',
    573574                        'BP_Walker_Nav_Menu_Checklist' => 'core',
    574575                        'BP_Walker_Nav_Menu'           => 'core',
     576                        'BP_Invitation_Manager'        => 'core',
     577                        'BP_Invitation'                => 'core',
    575578
    576579                        'BP_Core_Friends_Widget' => 'friends',
    577580
  • new file tests/phpunit/assets/invitations-extensions.php

    diff --git tests/phpunit/assets/invitations-extensions.php tests/phpunit/assets/invitations-extensions.php
    new file mode 100644
    index 000000000..4815cc7ce
    - +  
     1<?php
     2/**
     3 * The following implementations of BP_Attachment act as dummy plugins
     4 * for our unit tests
     5 */
     6class BPTest_Invitation_Manager_Extension extends BP_Invitation_Manager {
     7        public function __construct( $args = array() ) {
     8                parent::__construct( $args );
     9        }
     10
     11        public function run_send_action( BP_Invitation $invitation ) {
     12                return true;
     13        }
     14
     15        public function run_acceptance_action( $type = 'invite', $r  ) {
     16                return true;
     17        }
     18}
  • 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..9d8c73400
    - +  
     1<?php
     2
     3include_once BP_TESTS_DIR . 'assets/invitations-extensions.php';
     4
     5/**
     6 * @group core
     7 * @group invitations
     8 */
     9 class BP_Tests_Invitations extends BP_UnitTestCase {
     10        public function test_bp_invitations_add_invitation_vanilla() {
     11                $old_current_user = get_current_user_id();
     12
     13                $u1 = $this->factory->user->create();
     14                $u2 = $this->factory->user->create();
     15                $u3 = $this->factory->user->create();
     16                $this->set_current_user( $u1 );
     17
     18                $invites_class = new BPTest_Invitation_Manager_Extension();
     19
     20                // Create a couple of invitations.
     21                $invite_args = array(
     22                        'user_id'           => $u3,
     23                        'inviter_id'            => $u1,
     24                        'item_id'           => 1,
     25                        'send_invite'       => 'sent',
     26                );
     27                $i1 = $invites_class->add_invitation( $invite_args );
     28                $invite_args['inviter_id'] = $u2;
     29                $i2 = $invites_class->add_invitation( $invite_args );
     30
     31                $get_invites = array(
     32                        'user_id'        => $u3,
     33                        'fields'         => 'ids',
     34                );
     35                $invites = $invites_class->get_invitations( $get_invites );
     36                $this->assertEqualSets( array( $i1, $i2 ), $invites );
     37
     38                $this->set_current_user( $old_current_user );
     39        }
     40
     41        public function test_bp_invitations_add_invitation_avoid_duplicates() {
     42                $old_current_user = get_current_user_id();
     43
     44                $u1 = $this->factory->user->create();
     45                $u2 = $this->factory->user->create();
     46                $this->set_current_user( $u1 );
     47
     48                $invites_class = new BPTest_Invitation_Manager_Extension();
     49
     50                // Create an invitation.
     51                $invite_args = array(
     52                        'user_id'           => $u2,
     53                        'inviter_id'            => $u1,
     54                        'item_id'           => 1,
     55                        'send_invite'       => 'sent',
     56                );
     57                $i1 = $invites_class->add_invitation( $invite_args );
     58                // Attempt to create a duplicate.
     59                $this->assertFalse( $invites_class->add_invitation( $invite_args ) );
     60
     61                $this->set_current_user( $old_current_user );
     62        }
     63
     64        public function test_bp_invitations_add_invitation_invite_plus_request_should_accept() {
     65                $old_current_user = get_current_user_id();
     66
     67                $u1 = $this->factory->user->create();
     68                $u2 = $this->factory->user->create();
     69                $u3 = $this->factory->user->create();
     70                $this->set_current_user( $u1 );
     71
     72                $invites_class = new BPTest_Invitation_Manager_Extension();
     73
     74                // Create an invitation.
     75                $invite_args = array(
     76                        'user_id'           => $u3,
     77                        'inviter_id'            => $u1,
     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                        'item_id'           => 1,
     87                );
     88                $r1 = $invites_class->add_request( $request_args );
     89
     90                $get_invites = array(
     91                        'user_id'          => $u3,
     92                        'accepted'         => 'accepted'
     93                );
     94                $invites = $invites_class->get_invitations( $get_invites );
     95                $this->assertEqualSets( array( $i1 ), wp_list_pluck( $invites, 'id' ) );
     96
     97                $this->set_current_user( $old_current_user );
     98        }
     99
     100        public function test_bp_invitations_add_invitation_unsent_invite_plus_request_should_not_accept() {
     101                $old_current_user = get_current_user_id();
     102
     103                $u1 = $this->factory->user->create();
     104                $u2 = $this->factory->user->create();
     105                $u3 = $this->factory->user->create();
     106                $this->set_current_user( $u1 );
     107
     108                $invites_class = new BPTest_Invitation_Manager_Extension();
     109
     110                // Create an invitation.
     111                $invite_args = array(
     112                        'user_id'           => $u3,
     113                        'inviter_id'            => $u1,
     114                        'item_id'           => 1,
     115                        'send_invite'       => 0,
     116                );
     117                $i1 = $invites_class->add_invitation( $invite_args );
     118
     119                // Create a request.
     120                $request_args = array(
     121                        'user_id'           => $u3,
     122                        'item_id'           => 1,
     123                );
     124                $r1 = $invites_class->add_request( $request_args );
     125
     126                $get_invites = array(
     127                        'user_id'          => $u3,
     128                        'accepted'         => 'accepted'
     129                );
     130                $invites = $invites_class->get_invitations( $get_invites );
     131                $this->assertEqualSets( array(), wp_list_pluck( $invites, 'id' ) );
     132
     133                $this->set_current_user( $old_current_user );
     134        }
     135
     136        public function test_bp_invitations_add_invitation_unsent_invite_plus_request_then_send_invite_should_accept() {
     137                $old_current_user = get_current_user_id();
     138
     139                $u1 = $this->factory->user->create();
     140                $u2 = $this->factory->user->create();
     141                $u3 = $this->factory->user->create();
     142                $this->set_current_user( $u1 );
     143
     144                $invites_class = new BPTest_Invitation_Manager_Extension();
     145
     146                // Create an invitation.
     147                $invite_args = array(
     148                        'user_id'           => $u3,
     149                        'inviter_id'            => $u1,
     150                        'item_id'           => 1,
     151                        'send_invite'       => 0,
     152                );
     153                $i1 = $invites_class->add_invitation( $invite_args );
     154
     155                // Create a request.
     156                $request_args = array(
     157                        'user_id'           => $u3,
     158                        'item_id'           => 1,
     159                );
     160                $r1 = $invites_class->add_request( $request_args );
     161
     162                $invites_class->send_invitation_by_id( $i1 );
     163
     164                // Check that both the request and invitation are marked 'accepted'.
     165                $get_invites = array(
     166                        'user_id'          => $u3,
     167                        'type'             => 'all',
     168                        'accepted'         => 'accepted',
     169                        'fields'           => 'ids'
     170                );
     171                $invites = $invites_class->get_invitations( $get_invites );
     172                $this->assertEqualSets( array( $i1, $r1 ), $invites );
     173
     174                $this->set_current_user( $old_current_user );
     175        }
     176
     177        public function test_bp_invitations_add_request_vanilla() {
     178                $old_current_user = get_current_user_id();
     179
     180                $u1 = $this->factory->user->create();
     181                $this->set_current_user( $u1 );
     182
     183                $invites_class = new BPTest_Invitation_Manager_Extension();
     184
     185                // Create a couple of requests.
     186                $request_args = array(
     187                        'user_id'           => $u1,
     188                        'item_id'           => 7,
     189                );
     190                $r1 = $invites_class->add_request( $request_args );
     191                $request_args['item_id'] = 4;
     192                $r2 = $invites_class->add_request( $request_args );
     193
     194                $get_requests = array(
     195                        'user_id'           => $u1,
     196                        'fields'            => 'ids'
     197                );
     198                $requests = $invites_class->get_requests( $get_requests );
     199                $this->assertEqualSets( array( $r1, $r2 ), $requests );
     200
     201                $this->set_current_user( $old_current_user );
     202        }
     203
     204        public function test_bp_invitations_add_request_avoid_duplicates() {
     205                $old_current_user = get_current_user_id();
     206
     207                $invites_class = new BPTest_Invitation_Manager_Extension();
     208
     209                $u1 = $this->factory->user->create();
     210                $this->set_current_user( $u1 );
     211
     212                // Create a couple of requests.
     213                $request_args = array(
     214                        'user_id'           => $u1,
     215                        'item_id'           => 7,
     216                );
     217                $r1 = $invites_class->add_request( $request_args );
     218                // Attempt to create a duplicate.
     219                $this->assertFalse( $invites_class->add_request( $request_args ) );
     220
     221                $this->set_current_user( $old_current_user );
     222        }
     223
     224        public function test_bp_invitations_add_request_request_plus_sent_invite_should_accept() {
     225                $old_current_user = get_current_user_id();
     226
     227                $u1 = $this->factory->user->create();
     228                $u2 = $this->factory->user->create();
     229                $this->set_current_user( $u1 );
     230
     231                $invites_class = new BPTest_Invitation_Manager_Extension();
     232
     233                // Create a request.
     234                $request_args = array(
     235                        'user_id'           => $u2,
     236                        'item_id'           => 1,
     237                );
     238                $r1 = $invites_class->add_request( $request_args );
     239
     240                // Create an invitation.
     241                $invite_args = array(
     242                        'user_id'           => $u2,
     243                        'inviter_id'            => $u1,
     244                        'item_id'           => 1,
     245                        'send_invite'       => 1,
     246                );
     247                $i1 = $invites_class->add_invitation( $invite_args );
     248
     249                // Check that both the request and invitation are marked 'accepted'.
     250                $get_invites = array(
     251                        'user_id'          => $u2,
     252                        'type'             => 'all',
     253                        'accepted'         => 'accepted',
     254                        'fields'           => 'ids'
     255                );
     256                $invites = $invites_class->get_invitations( $get_invites );
     257                $this->assertEqualSets( array( $r1, $i1 ), $invites );
     258
     259                $this->set_current_user( $old_current_user );
     260        }
     261
     262        public function test_bp_invitations_sending_should_clear_cache() {
     263                $old_current_user = get_current_user_id();
     264
     265                $u1 = $this->factory->user->create();
     266                $u2 = $this->factory->user->create();
     267                $this->set_current_user( $u1 );
     268
     269                $invites_class = new BPTest_Invitation_Manager_Extension();
     270
     271                // Create an invitation.
     272                $invite_args = array(
     273                        'user_id'           => $u2,
     274                        'inviter_id'            => $u1,
     275                        'item_id'           => 1,
     276                );
     277                $i1 = $invites_class->add_invitation( $invite_args );
     278
     279                $invite = new BP_Invitation( $i1 );
     280                $this->assertEquals( 0, $invite->invite_sent );
     281
     282                $invites_class->send_invitation_by_id( $i1 );
     283
     284                $invite = new BP_Invitation( $i1 );
     285                $this->assertEquals( 1, $invite->invite_sent );
     286
     287                $this->set_current_user( $old_current_user );
     288        }
     289
     290}
  • 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..5021d6401 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 { 
    114115        public function test_total_group_count_groups_accept_invite() {
    115116                $u1 = self::factory()->user->create();
    116117                $u2 = self::factory()->user->create();
    117                 $g = self::factory()->group->create();
     118                $g = self::factory()->group->create( array( 'status' => 'private', 'creator_id' => $u2 ) );
     119
    118120                groups_invite_user( array(
    119121                        'user_id' => $u1,
    120122                        'group_id' => $g,
    121123                        'inviter_id' => $u2,
     124                        'send_invite' => 1,
    122125                ) );
    123126
    124                 groups_accept_invite( $u2, $g );
     127                groups_accept_invite( $u1, $g );
    125128
    126                 $this->assertEquals( 1, bp_get_user_meta( $u2, 'total_group_count', true ) );
     129                $this->assertEquals( 1, bp_get_user_meta( $u1, 'total_group_count', true ) );
    127130        }
    128131
    129132        /**
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    137140                $current_user = bp_loggedin_user_id();
    138141                $this->set_current_user( $u2 );
    139142
    140                 $g = self::factory()->group->create();
    141                 groups_send_membership_request( $u1, $g );
     143                $g = self::factory()->group->create( array( 'status' => 'private' ) );
     144                groups_send_membership_request( array(
     145                        'user_id'       => $u1,
     146                        'group_id'      => $g,
     147                ) );
    142148
    143149                groups_accept_membership_request( 0, $u1, $g );
    144150
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    241247        public function test_total_member_count_groups_accept_invite() {
    242248                $u1 = self::factory()->user->create();
    243249                $u2 = self::factory()->user->create();
    244                 $g = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     250                $g = self::factory()->group->create( array( 'status' => 'private', 'creator_id' => $u1 ) );
    245251                groups_invite_user( array(
    246                         'user_id' => $u1,
    247                         'group_id' => $g,
    248                         'inviter_id' => $u2,
     252                        'user_id'     => $u2,
     253                        'group_id'    => $g,
     254                        'inviter_id'  => $u1,
     255                        'send_invite' => 1,
    249256                ) );
    250257
    251258                groups_accept_invite( $u2, $g );
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    260267        public function test_total_member_count_groups_accept_membership_request() {
    261268                $u1 = self::factory()->user->create();
    262269                $u2 = self::factory()->user->create();
    263                 $g = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     270                $g = self::factory()->group->create( array( 'status' => 'private', 'creator_id' => $u1 ) );
    264271
    265                 groups_send_membership_request( $u2, $g );
     272                groups_send_membership_request( array(
     273                        'user_id'       => $u2,
     274                        'group_id'      => $g,
     275                ) );
    266276                groups_accept_membership_request( 0, $u2, $g );
    267277
    268278                $this->assertEquals( 2, groups_get_groupmeta( $g, 'total_member_count' ) );
    Bar!'; 
    632642        public function test_get_invite_count_for_user() {
    633643                $u1 = self::factory()->user->create();
    634644                $u2 = self::factory()->user->create();
    635                 $g = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     645                $g = self::factory()->group->create( array( 'creator_id' => $u1, 'status' => 'private' ) );
    636646
    637647                // create invitation
    638648                groups_invite_user( array(
    639649                        'user_id'    => $u2,
    640650                        'group_id'   => $g,
    641651                        'inviter_id' => $u1,
     652                        'send_invite' => 1
    642653                ) );
    643654
    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 
    650655                // assert invite count
    651656                $this->assertEquals( 1, groups_get_invite_count_for_user( $u2 ) );
    652657
    Bar!'; 
    890895         * @ticket BP7698
    891896         */
    892897        public function test_bp_groups_pending_requests_personal_data_exporter() {
    893                 groups_send_membership_request( self::$user_ids[0], self::$group_ids[0] );
     898                groups_send_membership_request( array(
     899                        'user_id'       => self::$user_ids[0],
     900                        'group_id'      => self::$group_ids[0],
     901                ) );
    894902
    895903                $test_user = new WP_User( self::$user_ids[0] );
    896904
    Bar!'; 
    907915         */
    908916        public function test_bp_groups_pending_sent_invitations_personal_data_exporter() {
    909917                groups_invite_user( array(
    910                         'user_id'    => self::$user_ids[1],
    911                         'group_id'   => self::$group_ids[0],
    912                         'inviter_id' => self::$user_ids[0],
     918                        'user_id'     => self::$user_ids[0],
     919                        'group_id'    => self::$group_ids[0],
     920                        'inviter_id'  => self::$user_ids[2],
     921                        'send_invite' => 1,
    913922                ) );
    914923
    915                 $test_user = new WP_User( self::$user_ids[0] );
     924                $test_user = new WP_User( self::$user_ids[2] );
    916925
    917926                $actual = bp_groups_pending_sent_invitations_personal_data_exporter( $test_user->user_email, 1 );
    918927
    Bar!'; 
    929938                groups_invite_user( array(
    930939                        'user_id'    => self::$user_ids[0],
    931940                        'group_id'   => self::$group_ids[0],
    932                         'inviter_id' => self::$user_ids[1],
     941                        'inviter_id' => self::$user_ids[2],
    933942                ) );
    934943
    935944                $test_user = new WP_User( self::$user_ids[0] );
  • 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..645e88137 100644
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    2626                ) );
    2727                self::$groups = $f->group->create_many( 4, array(
    2828                        'creator_id' => self::$admin_user,
     29                        'status'     => 'private'
    2930                ) );
    3031
    3132                $now = time();
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    394395                ) );
    395396
    396397                groups_invite_user( array(
    397                         'user_id' => self::$user,
    398                         'group_id' => self::$groups[2],
    399                         'inviter_id' => self::$admin_user,
     398                        'user_id'     => self::$user,
     399                        'group_id'    => self::$groups[2],
     400                        'inviter_id'  => self::$admin_user,
     401                        'send_invite' => 1
    400402                ) );
    401403
    402404                $expected = array( self::$groups[0], self::$groups[1], self::$groups[2] );
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    412414         */
    413415        public function test_cache_should_be_invalidated_on_group_uninvite() {
    414416                groups_invite_user( array(
    415                         'user_id' => self::$user,
    416                         'group_id' => self::$groups[2],
    417                         'inviter_id' => self::$admin_user,
     417                        'user_id'     => self::$user,
     418                        'group_id'    => self::$groups[2],
     419                        'inviter_id'  => self::$admin_user,
     420                        'send_invite' => 1,
    418421                ) );
    419422
    420423                // Populate cache.
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    437440         */
    438441        public function test_cache_should_be_invalidated_on_group_invite_acceptance() {
    439442                groups_invite_user( array(
    440                         'user_id' => self::$user,
    441                         'group_id' => self::$groups[2],
    442                         'inviter_id' => self::$admin_user,
     443                        'user_id'     => self::$user,
     444                        'group_id'    => self::$groups[2],
     445                        'inviter_id'  => self::$admin_user,
     446                        'send_invite' => 1
    443447                ) );
    444448
    445449                // Populate cache.
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    458462         */
    459463        public function test_cache_should_be_invalidated_on_group_invite_reject() {
    460464                groups_invite_user( array(
    461                         'user_id' => self::$user,
    462                         'group_id' => self::$groups[2],
    463                         'inviter_id' => self::$admin_user,
     465                        'user_id'     => self::$user,
     466                        'group_id'    => self::$groups[2],
     467                        'inviter_id'  => self::$admin_user,
     468                        'send_invite' => 1
    464469                ) );
    465470
    466471                // Populate cache.
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    483488         */
    484489        public function test_cache_should_be_invalidated_on_group_invite_delete() {
    485490                groups_invite_user( array(
    486                         'user_id' => self::$user,
    487                         'group_id' => self::$groups[2],
    488                         'inviter_id' => self::$admin_user,
     491                        'user_id'     => self::$user,
     492                        'group_id'    => self::$groups[2],
     493                        'inviter_id'  => self::$admin_user,
     494                        'send_invite' => 1
    489495                ) );
    490496
    491497                // Populate cache.
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    516522                $server_name = isset( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : null;
    517523                $_SERVER['SERVER_NAME'] = '';
    518524
    519                 groups_send_membership_request( self::$user, self::$groups[2] );
     525                groups_send_membership_request( array(
     526                        'user_id' => self::$user,
     527                        'group_id' => self::$groups[2]
     528                ) );
    520529
    521530                // For `wp_mail()`.
    522531                if ( is_null( $server_name ) ) {
    class BP_Tests_Groups_Functions_BpGetUserGroups extends BP_UnitTestCase { 
    541550                $server_name = isset( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : null;
    542551                $_SERVER['SERVER_NAME'] = '';
    543552
    544                 groups_send_membership_request( self::$user, self::$groups[2] );
     553                groups_send_membership_request( array(
     554                        'user_id'       => self::$user,
     555                        'group_id'      => self::$groups[2],
     556                ) );
    545557
    546558                // Populate cache.
    547559                $g1 = bp_get_user_groups( self::$user );
    548560
    549561                $m = new BP_Groups_Member( self::$user, self::$groups[2] );
    550562
    551                 groups_accept_membership_request( $m->id, self::$user, self::$groups[2] );
     563                groups_accept_membership_request( false, self::$user, self::$groups[2] );
    552564
    553565                // For `wp_mail()`.
    554566                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/notifications.php

    diff --git tests/phpunit/testcases/groups/notifications.php tests/phpunit/testcases/groups/notifications.php
    index c844c91ef..2aafb30e0 100644
    class BP_Tests_Groups_Notifications extends BP_UnitTestCase { 
    1616                $this->set_current_user( self::factory()->user->create() );
    1717
    1818                $this->requesting_user_id = self::factory()->user->create();
    19                 $this->group = self::factory()->group->create();
     19                $this->group = self::factory()->group->create( array( 'status' =>  'private' ) );
    2020                $this->filter_fired = '';
    2121        }
    2222
    class BP_Tests_Groups_Notifications extends BP_UnitTestCase { 
    232232                        'is_admin' => 1,
    233233                ) );
    234234
    235                 groups_send_membership_request( $users[2], $this->group );
     235                groups_send_membership_request( array(
     236                        'user_id' => $users[2],
     237                        'group_id' => $this->group
     238                ) );
    236239
    237240                // Both admins should get a notification.
    238241                $get_args = array(
    class BP_Tests_Groups_Notifications extends BP_UnitTestCase { 
    247250                $this->assertNotEmpty( $u0_notifications );
    248251                $this->assertNotEmpty( $u1_notifications );
    249252
    250                 $this->assertTrue( groups_invite_user( array(
     253                groups_accept_membership_request( false, $users[2], $this->group );
     254
     255                $u0_notifications = BP_Notifications_Notification::get( $get_args );
     256                $u1_notifications = BP_Notifications_Notification::get( $get_args );
     257                $this->assertEmpty( $u0_notifications );
     258                $this->assertEmpty( $u1_notifications );
     259        }
     260
     261        public function test_membership_request_notifications_should_be_cleared_when_request_is_accepted_via_invite() {
     262                $users = self::factory()->user->create_many( 3 );
     263
     264                $this->add_user_to_group( $users[0], $this->group, array(
     265                        'is_admin' => 1,
     266                ) );
     267                $this->add_user_to_group( $users[1], $this->group, array(
     268                        'is_admin' => 1,
     269                ) );
     270
     271                groups_send_membership_request( array(
     272                        'user_id' => $users[2],
     273                        'group_id' => $this->group
     274                ) );
     275
     276                // Both admins should get a notification.
     277                $get_args = array(
     278                        'user_id' => $users[0],
     279                        'item_id' => $this->group,
     280                        'secondary_item_id' => $users[2],
     281                        'component_action' => 'new_membership_request',
     282                        'is_new' => true,
     283                );
     284                $u0_notifications = BP_Notifications_Notification::get( $get_args );
     285                $u1_notifications = BP_Notifications_Notification::get( $get_args );
     286                $this->assertNotEmpty( $u0_notifications );
     287                $this->assertNotEmpty( $u1_notifications );
     288
     289                // 'Accept' the request by sending an invite.
     290                groups_invite_user( array(
    251291                        'user_id' => $users[2],
    252292                        'group_id' => $this->group,
    253                 ) ) );
     293                        'send_invite' => true
     294                ) );
    254295
    255296                $u0_notifications = BP_Notifications_Notification::get( $get_args );
    256297                $u1_notifications = BP_Notifications_Notification::get( $get_args );
  • 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..eba64ac53 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        }
    class BP_Tests_Groups_User_Can_Filter extends BP_UnitTestCase { 
    126129                $this->assertFalse( bp_user_can( $u1, 'groups_request_membership', array( 'group_id' => $g1 ) ) );
    127130        }
    128131
    129         public function test_user_cannot_receive_invitation_to_public_group() {
    130                 $g1 = $this->factory->group->create( array(
    131                         'status'      => 'public'
    132                 ) );
    133                 $u1 = $this->factory->user->create();
    134 
    135                 $this->assertFalse( bp_user_can( $u1, 'groups_receive_invitation', array( 'group_id' => $g1 ) ) );
    136         }
    137 
    138132        public function test_user_can_receive_invitation_to_private_group() {
    139133                $g1 = $this->factory->group->create( array(
    140134                        'status'      => 'private'