Skip to:
Content

bbPress.org

Changeset 6725


Ignore:
Timestamp:
10/11/2017 06:55:03 PM (2 years ago)
Author:
johnjamesjacoby
Message:

Subscriptions: Introduce bbp_get_email_addresses_from_user_ids() to chunk get_users() calls.

This changes the strategy used when querying for subscribed users so that not of them are queried at the same time, which could cause timeouts or out-of-memory issues when there are many users subscribed to a forum or topic.

By default, users are now queried in 100 user increments, and each 100 user chunk of email addresses gets merged into 1 large array and returned. The 100 default also has a filter, so it's somewhat configurable. Duplicate email addresses are strictly avoided, and user ID filters were moved to after the current user ID is removed from the array, which allows for third party plugins to add them back in if they'd like to include them.

See #3068.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/common/functions.php

    r6711 r6725  
    10601060    $user_ids = bbp_get_subscribers( $topic_id );
    10611061
    1062     // Dedicated filter to manipulate user ID's to send emails to
    1063     $user_ids = (array) apply_filters( 'bbp_topic_subscription_user_ids', $user_ids );
    1064     if ( empty( $user_ids ) ) {
    1065         return false;
    1066     }
    1067 
    10681062    // Remove the reply author from the list.
    10691063    $reply_author_key = array_search( (int) $reply_author, $user_ids, true );
    10701064    if ( false !== $reply_author_key ) {
    1071         unset( $user_ids[ $reply_author_key ] );
    1072     }
     1065        //unset( $user_ids[ $reply_author_key ] );
     1066    }
     1067
     1068    // Dedicated filter to manipulate user ID's to send emails to
     1069    $user_ids = (array) apply_filters( 'bbp_topic_subscription_user_ids', $user_ids );
    10731070
    10741071    // Bail of the reply author was the only one subscribed.
    10751072    if ( empty( $user_ids ) ) {
     1073        return false;
     1074    }
     1075
     1076    // Get email addresses, bail if empty
     1077    $email_addresses = bbp_get_email_addresses_from_user_ids( $user_ids );
     1078    if ( empty( $email_addresses ) ) {
    10761079        return false;
    10771080    }
     
    11311134    $headers = array( 'From: ' . get_bloginfo( 'name' ) . ' <' . $from_email . '>' );
    11321135
    1133     // Loop through users
    1134     foreach ( (array) $user_ids as $user_id ) {
    1135         $headers[] = 'Bcc: ' . get_userdata( $user_id )->user_email;
     1136    // Loop through addresses
     1137    foreach ( (array) $email_addresses as $address ) {
     1138        $headers[] = 'Bcc: ' . $address;
    11361139    }
    11371140
     
    12131216    $user_ids = bbp_get_subscribers( $forum_id );
    12141217
    1215     // Dedicated filter to manipulate user ID's to send emails to
    1216     $user_ids = (array) apply_filters( 'bbp_forum_subscription_user_ids', $user_ids );
    1217     if ( empty( $user_ids ) ) {
    1218         return false;
    1219     }
    1220 
    12211218    // Remove the topic author from the list.
    12221219    $topic_author_key = array_search( (int) $topic_author, $user_ids, true );
     
    12251222    }
    12261223
    1227     // Bail of the topic author was the only one subscribed.
     1224    // Dedicated filter to manipulate user ID's to send emails to
     1225    $user_ids = (array) apply_filters( 'bbp_forum_subscription_user_ids', $user_ids );
     1226
     1227    // Bail of the reply author was the only one subscribed.
    12281228    if ( empty( $user_ids ) ) {
     1229        return false;
     1230    }
     1231
     1232    // Get email addresses, bail if empty
     1233    $email_addresses = bbp_get_email_addresses_from_user_ids( $user_ids );
     1234    if ( empty( $email_addresses ) ) {
    12291235        return false;
    12301236    }
     
    12841290    $headers = array( 'From: ' . get_bloginfo( 'name' ) . ' <' . $from_email . '>' );
    12851291
    1286     // Loop through users
    1287     foreach ( (array) $user_ids as $user_id ) {
    1288         $headers[] = 'Bcc: ' . get_userdata( $user_id )->user_email;
     1292    // Loop through addresses
     1293    foreach ( (array) $email_addresses as $address ) {
     1294        $headers[] = 'Bcc: ' . $address;
    12891295    }
    12901296
     
    13311337function bbp_notify_subscribers( $reply_id = 0, $topic_id = 0, $forum_id = 0, $anonymous_data = array(), $reply_author = 0 ) {
    13321338    return bbp_notify_topic_subscribers( $reply_id, $topic_id, $forum_id, $anonymous_data, $reply_author );
     1339}
     1340
     1341/**
     1342 * Return an array of user email addresses from an array of user IDs
     1343 *
     1344 * @since 2.6.0 bbPress (r6722)
     1345 *
     1346 * @param array $user_ids
     1347 * @return array
     1348 */
     1349function bbp_get_email_addresses_from_user_ids( $user_ids = array() ) {
     1350
     1351    // Default return value
     1352    $retval = array();
     1353
     1354    // Maximum number of users to get per database query
     1355    $limit = apply_filters( 'bbp_get_users_chunk_limit', 100 );
     1356
     1357    // Only do the work if there are user IDs to query for
     1358    if ( ! empty( $user_ids ) ) {
     1359
     1360        // Get total number of sets
     1361        $steps = ceil( count( $user_ids ) / $limit );
     1362
     1363        // Loop through users
     1364        foreach ( range( 1, $steps ) as $loop ) {
     1365
     1366            // Initial loop has no offset
     1367            $offset = ( 1 === $loop )
     1368                ? 1
     1369                : $limit * $loop;
     1370
     1371            // Calculate user IDs to include
     1372            $loop_ids = array_slice( $user_ids, $offset, $limit );
     1373
     1374            // Call get_users() in a way that users are cached
     1375            $loop_users = get_users( array(
     1376                'blog_id' => 0,
     1377                'fields'  => 'all_with_meta',
     1378                'include' => $loop_ids
     1379            ) );
     1380
     1381            // Pluck emails from users
     1382            $loop_emails = wp_list_pluck( $loop_users, 'user_email' );
     1383
     1384            // Clean-up memory, for big user sets
     1385            unset( $loop_users );
     1386
     1387            // Merge users into return value
     1388            if ( ! empty( $loop_emails ) ) {
     1389                $retval = array_merge( $retval, $loop_emails );
     1390            }
     1391        }
     1392
     1393        // No duplicates
     1394        $retval = bbp_get_unique_array_values( $retval );
     1395    }
     1396
     1397    // Filter & return
     1398    return apply_filters( 'bbp_get_email_addresses_from_user_ids', $retval, $user_ids, $limit );
    13331399}
    13341400
Note: See TracChangeset for help on using the changeset viewer.