Skip to:
Content

BuddyPress.org


Ignore:
Timestamp:
08/31/2021 09:46:50 PM (5 months ago)
Author:
dcavins
Message:

Improve BP_Signup class.

  • Add caching for BP_Signup SQL queries and BP_Signup objects.
  • Synchronize signup result format provided by get() and construct() methods.
  • Add action points so that the cache items can be cleaned up.
  • Use cached functions rather than making direct database calls.
  • Improve behavior of meta updating method.

Fixes #8540.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-members/classes/class-bp-signup.php

    r12768 r13098  
    7979    public $activation_key;
    8080
     81    /**
     82     * The activated date for the user.
     83     *
     84     * @since 10.0.0
     85     * @var string
     86     */
     87    public $activated;
     88
     89    /**
     90     * Whether the user account is activated or not.
     91     *
     92     * @since 10.0.0
     93     * @var bool
     94     */
     95    public $active;
     96
     97    /**
     98     * The date that the last activation email was sent.
     99     *
     100     * @since 10.0.0
     101     * @var string
     102     */
     103    public $date_sent;
     104
     105    /**
     106     * Was the last activation email sent in the last 24 hours?
     107     *
     108     * @since 10.0.0
     109     * @var bool
     110     */
     111    public $recently_sent;
     112
     113    /**
     114     * The number of activation emails sent to this user.
     115     *
     116     * @since 10.0.0
     117     * @var int
     118     */
     119    public $count_sent;
     120
     121    /**
     122     * The domain for the signup.
     123     *
     124     * @since 10.0.0
     125     * @var string
     126     */
     127    public $domain;
     128
     129    /**
     130     * The path for the signup.
     131     *
     132     * @since 10.0.0
     133     * @var string
     134     */
     135    public $path;
     136
     137    /**
     138     * The title for the signup.
     139     *
     140     * @since 10.0.0
     141     * @var string
     142     */
     143    public $title;
     144
    81145
    82146    /** Public Methods *******************************************************/
     
    90154     */
    91155    public function __construct( $signup_id = 0 ) {
    92         if ( !empty( $signup_id ) ) {
     156        if ( ! empty( $signup_id ) ) {
    93157            $this->id = $signup_id;
    94158            $this->populate();
     
    104168        global $wpdb;
    105169
    106         $signups_table = buddypress()->members->table_name_signups;
    107         $signup        = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$signups_table} WHERE signup_id = %d AND active = 0", $this->id ) );
    108 
    109         $this->avatar         = get_avatar( $signup->user_email, 32 );
     170        // Get BuddyPress.
     171        $bp = buddypress();
     172
     173        // Check cache for signup data.
     174        $signup = wp_cache_get( $this->id, 'bp_signups' );
     175
     176        // Cache missed, so query the DB.
     177        if ( false === $signup ) {
     178            $signup = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->members->table_name_signups} WHERE signup_id = %d", $this->id ) );
     179
     180            wp_cache_set( $this->id, $signup, 'bp_signups' );
     181        }
     182
     183        // No signup found so set the ID and bail.
     184        if ( empty( $signup ) || is_wp_error( $signup ) ) {
     185            $this->id = 0;
     186            return;
     187        }
     188
     189        /*
     190         * Add every db column to the object.
     191         */
     192        $this->signup_id      = $this->id;
     193        $this->domain         = $signup->domain;
     194        $this->path           = $signup->path;
     195        $this->title          = $signup->title;
    110196        $this->user_login     = $signup->user_login;
    111197        $this->user_email     = $signup->user_email;
     198        $this->registered     = $signup->registered;
     199        $this->activated      = $signup->activated;
     200        $this->active         = (bool) $signup->active;
     201        $this->activation_key = $signup->activation_key;
    112202        $this->meta           = maybe_unserialize( $signup->meta );
    113         $this->user_name      = ! empty( $this->meta['field_1'] ) ? wp_unslash( $this->meta['field_1'] ) : '';
    114         $this->registered     = $signup->registered;
    115         $this->activation_key = $signup->activation_key;
     203
     204        // Add richness.
     205        $this->avatar    = get_avatar( $signup->user_email, 32 );
     206        $this->user_name = ! empty( $this->meta['field_1'] ) ? wp_unslash( $this->meta['field_1'] ) : '';
     207
     208        // When was the activation email sent?
     209        if ( isset( $this->meta['sent_date'] ) && '0000-00-00 00:00:00' !== $this->meta['sent_date'] ) {
     210            $this->date_sent = $this->meta['sent_date'];
     211
     212            // Sent date defaults to date of registration.
     213        } else {
     214            $this->date_sent = $signup->registered;
     215        }
     216
     217        /**
     218         * Calculate a diff between now & last time
     219         * an activation link has been resent.
     220         */
     221        $sent_at = mysql2date( 'U', $this->date_sent );
     222        $now     = current_time( 'timestamp', true );
     223        $diff    = $now - $sent_at;
     224
     225        /**
     226         * Set a boolean to track whether an activation link
     227         * was sent in the last day.
     228         */
     229        $this->recently_sent = ( $diff < 1 * DAY_IN_SECONDS );
     230
     231        // How many times has the activation email been sent?
     232        if ( isset( $this->meta['count_sent'] ) ) {
     233            $this->count_sent = absint( $this->meta['count_sent'] );
     234        } else {
     235            $this->count_sent = 0;
     236        }
    116237    }
    117238
     
    127248     *     The argument to retrieve desired signups.
    128249     *     @type int         $offset         Offset amount. Default 0.
    129      *     @type int         $number         How many to fetch. Default 1.
     250     *     @type int         $number         How many to fetch. Pass -1 to fetch all. Default 1.
    130251     *     @type bool|string $usersearch     Whether or not to search for a username. Default false.
    131252     *     @type string      $orderby        Order By parameter. Possible values are `signup_id`, `login`, `email`,
     
    133254     *     @type string      $order          Order direction. Default 'DESC'.
    134255     *     @type bool        $include        Whether or not to include more specific query params.
    135      *     @type string      $activation_key Activation key to search for.
     256     *     @type string      $activation_key Activation key to search for. If specified, all other
     257     *                                       parameters will be ignored.
    136258     *     @type string      $user_login     Specific user login to return.
    137259     *     @type string      $fields         Which fields to return. Specify 'ids' to fetch a list of signups IDs.
     
    146268        global $wpdb;
    147269
    148         $r = bp_parse_args( $args,
     270        $bp = buddypress();
     271        $r  = bp_parse_args(
     272            $args,
    149273            array(
    150274                'offset'         => 0,
     
    155279                'include'        => false,
    156280                'activation_key' => '',
     281                'user_email'     => '',
    157282                'user_login'     => '',
    158283                'fields'         => 'all',
     
    172297        $r['orderby'] = sanitize_title( $r['orderby'] );
    173298
    174         $sql = array();
    175         $signups_table  = buddypress()->members->table_name_signups;
    176         $sql['select']  = "SELECT * FROM {$signups_table}";
    177         $sql['where']   = array();
    178         $sql['where'][] = "active = 0";
    179 
    180         if ( empty( $r['include'] ) ) {
     299        $sql = array(
     300            'select'     => "SELECT DISTINCT signup_id",
     301            'from'       => "{$bp->members->table_name_signups}",
     302            'where'      => array(),
     303            'orderby'    => '',
     304            'limit'      => '',
     305        );
     306
     307        // Activation key trumps other parameters because it should be unique.
     308        if ( ! empty( $r['activation_key'] ) ) {
     309            $sql['where'][] = $wpdb->prepare( "activation_key = %s", $r['activation_key'] );
     310
     311            // `Include` finds signups by ID.
     312        } else if ( ! empty( $r['include'] ) ) {
     313
     314            $in             = implode( ',', wp_parse_id_list( $r['include'] ) );
     315            $sql['where'][] = "signup_id IN ({$in})";
     316
     317            /**
     318             * Finally, the general case where a variety of parameters
     319             * can be used in combination to find signups.
     320             */
     321        } else {
    181322
    182323            // Search terms.
     
    186327            }
    187328
    188             // Activation key.
    189             if ( ! empty( $r['activation_key'] ) ) {
    190                 $sql['where'][] = $wpdb->prepare( "activation_key = %s", $r['activation_key'] );
     329            // User email.
     330            if ( ! empty( $r['user_email'] ) ) {
     331                $sql['where'][] = $wpdb->prepare( "user_email = %s", $r['user_email'] );
    191332            }
    192333
     
    196337            }
    197338
    198             $sql['orderby'] = "ORDER BY {$r['orderby']}";
    199             $sql['order']   = bp_esc_sql_order( $r['order'] );
    200             $sql['limit']   = $wpdb->prepare( "LIMIT %d, %d", $r['offset'], $r['number'] );
    201         } else {
    202             $in = implode( ',', wp_parse_id_list( $r['include'] ) );
    203             $sql['in'] = "AND signup_id IN ({$in})";
     339            $order          = bp_esc_sql_order( $r['order'] );
     340            $sql['orderby'] = "ORDER BY {$r['orderby']} {$order}";
     341
     342            $number = intval( $r['number'] );
     343            if ( -1 !== $number ) {
     344                $sql['limit'] = $wpdb->prepare( "LIMIT %d, %d", absint( $r['offset'] ), $number );
     345            }
    204346        }
    205347
    206348        // Implode WHERE clauses.
    207349        $sql['where'] = 'WHERE ' . implode( ' AND ', $sql['where'] );
     350
     351        $paged_signups_sql = "{$sql['select']} FROM {$sql['from']} {$sql['where']} {$sql['orderby']} {$sql['limit']}";
    208352
    209353        /**
     
    217361         * @param array  $r     Array of parsed arguments for get() method.
    218362         */
    219         $paged_signups = $wpdb->get_results( apply_filters( 'bp_members_signups_paged_query', join( ' ', $sql ), $sql, $args, $r ) );
    220 
    221         if ( empty( $paged_signups ) ) {
    222             return array( 'signups' => false, 'total' => false );
     363        $paged_signups_sql = apply_filters( 'bp_members_signups_paged_query', $paged_signups_sql, $sql, $args, $r );
     364
     365        $cached = bp_core_get_incremented_cache( $paged_signups_sql, 'bp_signups' );
     366        if ( false === $cached ) {
     367            $paged_signup_ids = $wpdb->get_col( $paged_signups_sql );
     368            bp_core_set_incremented_cache( $paged_signups_sql, 'bp_signups', $paged_signup_ids );
     369        } else {
     370            $paged_signup_ids = $cached;
    223371        }
    224372
    225373        // We only want the IDs.
    226374        if ( 'ids' === $r['fields'] ) {
    227             $paged_signups = wp_list_pluck( $paged_signups, 'signup_id' );
     375            $paged_signups = array_map( 'intval', $paged_signup_ids );
     376
    228377        } else {
    229 
    230             // Used to calculate a diff between now & last
    231             // time an activation link has been resent.
    232             $now = current_time( 'timestamp', true );
    233 
    234             foreach ( (array) $paged_signups as $key => $signup ) {
    235 
    236                 $signup->id   = intval( $signup->signup_id );
    237 
    238                 $signup->meta = ! empty( $signup->meta ) ? maybe_unserialize( $signup->meta ) : false;
    239 
    240                 $signup->user_name = '';
    241                 if ( ! empty( $signup->meta['field_1'] ) ) {
    242                     $signup->user_name = wp_unslash( $signup->meta['field_1'] );
     378            $uncached_signup_ids = bp_get_non_cached_ids( $paged_signup_ids, 'bp_signups' );
     379            if ( $uncached_signup_ids ) {
     380                $signup_ids_sql      = implode( ',', array_map( 'intval', $uncached_signup_ids ) );
     381                $signup_data_objects = $wpdb->get_results( "SELECT * FROM {$bp->members->table_name_signups} WHERE signup_id IN ({$signup_ids_sql})" );
     382                foreach ( $signup_data_objects as $signup_data_object ) {
     383                    wp_cache_set( $signup_data_object->signup_id, $signup_data_object, 'bp_signups' );
    243384                }
    244 
    245                 // Sent date defaults to date of registration.
    246                 if ( ! empty( $signup->meta['sent_date'] ) ) {
    247                     $signup->date_sent = $signup->meta['sent_date'];
    248                 } else {
    249                     $signup->date_sent = $signup->registered;
    250                 }
    251 
    252                 $sent_at = mysql2date('U', $signup->date_sent );
    253                 $diff    = $now - $sent_at;
    254 
    255                 /**
    256                  * Add a boolean in case the last time an activation link
    257                  * has been sent happened less than a day ago.
    258                  */
    259                 if ( $diff < 1 * DAY_IN_SECONDS ) {
    260                     $signup->recently_sent = true;
    261                 }
    262 
    263                 if ( ! empty( $signup->meta['count_sent'] ) ) {
    264                     $signup->count_sent = absint( $signup->meta['count_sent'] );
    265                 } else {
    266                     $signup->count_sent = 1;
    267                 }
    268 
    269                 $paged_signups[ $key ] = $signup;
    270385            }
    271         }
    272 
    273         unset( $sql['limit'] );
    274         $sql['select'] = preg_replace( "/SELECT.*?FROM/", "SELECT COUNT(*) FROM", $sql['select'] );
     386
     387            $paged_signups = array();
     388            foreach ( $paged_signup_ids as $paged_signup_id ) {
     389                $paged_signups[] = new BP_Signup( $paged_signup_id );
     390            }
     391        }
     392
     393        // Find the total number of signups in the results set.
     394        $total_signups_sql = "SELECT COUNT(DISTINCT signup_id) FROM {$sql['from']} {$sql['where']}";
    275395
    276396        /**
     
    284404         * @param array  $r     Array of parsed arguments for get() method.
    285405         */
    286         $total_signups = $wpdb->get_var( apply_filters( 'bp_members_signups_count_query', join( ' ', $sql ), $sql, $args, $r ) );
     406        $total_signups_sql = apply_filters( 'bp_members_signups_count_query', $total_signups_sql, $sql, $args, $r );
     407
     408        $cached = bp_core_get_incremented_cache( $total_signups_sql, 'bp_signups' );
     409        if ( false === $cached ) {
     410            $total_signups = (int) $wpdb->get_var( $total_signups_sql );
     411            bp_core_set_incremented_cache( $total_signups_sql, 'bp_signups', $total_signups );
     412        } else {
     413            $total_signups = (int) $cached;
     414        }
    287415
    288416        return array( 'signups' => $paged_signups, 'total' => $total_signups );
     
    310438        global $wpdb;
    311439
    312         $r = bp_parse_args( $args,
     440        $r = bp_parse_args(
     441            $args,
    313442            array(
    314443                'domain'         => '',
     
    319448                'registered'     => current_time( 'mysql', true ),
    320449                'activation_key' => '',
    321                 'meta'           => '',
     450                'meta'           => array(),
    322451            ),
    323452            'bp_core_signups_add_args'
    324453        );
     454
     455        // Ensure that sent_date and count_sent are set in meta.
     456        if ( ! isset( $r['meta']['sent_date'] ) ) {
     457            $r['meta']['sent_date'] = '0000-00-00 00:00:00';
     458        }
     459        if ( ! isset( $r['meta']['count_sent'] ) ) {
     460            $r['meta']['count_sent'] = 0;
     461        }
    325462
    326463        $r['meta'] = maybe_serialize( $r['meta'] );
     
    339476
    340477        /**
     478         * Fires after adding a new BP_Signup.
     479         *
     480         * @since 10.0.0
     481         *
     482         * @param int|bool $retval ID of the BP_Signup just added.
     483         * @param array    $r      Array of parsed arguments for add() method.
     484         * @param array    $args   Array of original arguments for add() method.
     485         */
     486        do_action( 'bp_core_signups_after_add', $retval, $r, $args );
     487
     488        /**
    341489         * Filters the result of a signup addition.
    342490         *
    343491         * @since 2.0.0
    344492         *
    345          * @param int|bool $retval Newly added user ID on success, false on failure.
     493         * @param int|bool $retval Newly added signup ID on success, false on failure.
    346494         */
    347495        return apply_filters( 'bp_core_signups_add', $retval );
     
    369517        global $wpdb;
    370518
    371         $user_id = wp_insert_user( array(
    372             'user_login'   => $user_login,
    373             'user_pass'    => $user_password,
    374             'display_name' => sanitize_title( $user_login ),
    375             'user_email'   => $user_email
    376         ) );
     519        $user_id = wp_insert_user(
     520            array(
     521                'user_login'   => $user_login,
     522                'user_pass'    => $user_password,
     523                'display_name' => sanitize_title( $user_login ),
     524                'user_email'   => $user_email
     525            )
     526        );
    377527
    378528        if ( is_wp_error( $user_id ) || empty( $user_id ) ) {
     
    422572
    423573        /**
     574         * Fires after adding a new WP User (backcompat).
     575         *
     576         * @since 10.0.0
     577         *
     578         * @param int $user_id ID of the WP_User just added.
     579         */
     580        do_action( 'bp_core_signups_after_add_backcompat', $user_id );
     581
     582        /**
    424583         * Filters the user ID for the backcompat functionality.
    425584         *
     
    446605        }
    447606
    448         $user_status = $wpdb->get_var( $wpdb->prepare( "SELECT user_status FROM {$wpdb->users} WHERE ID = %d", $user_id ) );
     607        $user        = get_user_by( 'id', $user_id );
     608        $user_status = $user->user_status;
    449609
    450610        /**
     
    512672     */
    513673    public static function count_signups() {
    514         global $wpdb;
    515 
    516         $signups_table = buddypress()->members->table_name_signups;
    517         $count_signups = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) AS total FROM {$signups_table} WHERE active = %d", 0 ) );
     674        $all_signups   = self::get(
     675            array(
     676                'fields' => 'ids',
     677            )
     678        );
     679        $count_signups = $all_signups['total'];
    518680
    519681        /**
     
    545707        global $wpdb;
    546708
    547         $r = bp_parse_args( $args,
     709        $r = bp_parse_args(
     710            $args,
    548711            array(
    549712                'signup_id'  => 0,
     
    557720        }
    558721
     722        $signup_id = absint( $r['signup_id'] );
     723
     724        // Figure out which meta keys should be updated.
     725        $signup       = new BP_Signup( $signup_id );
     726        $blended_meta = wp_parse_args( $r['meta'], $signup->meta );
     727
    559728        $wpdb->update(
    560729            // Signups table.
     
    562731            // Data to update.
    563732            array(
    564                 'meta' => serialize( $r['meta'] ),
     733                'meta' => serialize( $blended_meta ),
    565734            ),
    566735            // WHERE.
    567736            array(
    568                 'signup_id' => $r['signup_id'],
     737                'signup_id' => $signup_id,
    569738            ),
    570739            // Data sanitization format.
     
    579748
    580749        /**
     750         * Fires after updating the meta of a new BP_Signup.
     751         *
     752         * @since 10.0.0
     753         *
     754         * @param int|bool $signup_id    ID of the BP_Signup updated.
     755         * @param array    $r            Array of parsed arguments to update() method.
     756         * @param array    $args         Array of original arguments to update() method.
     757         * @param array    $blended_meta The complete set of meta to save.
     758         */
     759        do_action( 'bp_core_signups_after_update_meta', $signup_id, $r, $args, $blended_meta );
     760
     761        /**
    581762         * Filters the signup ID which received a meta update.
    582763         *
     
    601782        }
    602783
    603         $to_resend = self::get( array(
    604             'include' => $signup_ids,
    605         ) );
     784        $to_resend = self::get(
     785            array(
     786                'include' => $signup_ids,
     787            )
     788        );
    606789
    607790        if ( ! $signups = $to_resend['signups'] ) {
     
    622805        foreach ( $signups as $signup ) {
    623806
    624             $meta               = $signup->meta;
    625             $meta['sent_date']  = current_time( 'mysql', true );
    626             $meta['count_sent'] = $signup->count_sent + 1;
     807            $meta = array(
     808                'sent_date'  => current_time( 'mysql', true ),
     809                'count_sent' => $signup->count_sent + 1
     810            );
    627811
    628812            // Send activation email.
     
    656840
    657841            // Update metas.
    658             $result['resent'][] = self::update( array(
    659                 'signup_id' => $signup->signup_id,
    660                 'meta'      => $meta,
    661             ) );
     842            $result['resent'][] = self::update(
     843                array(
     844                    'signup_id' => $signup->signup_id,
     845                    'meta'      => $meta,
     846                )
     847            );
    662848        }
    663849
     
    695881        }
    696882
    697         $to_activate = self::get( array(
    698             'include' => $signup_ids,
    699         ) );
     883        $to_activate = self::get(
     884            array(
     885                'include' => $signup_ids,
     886            )
     887        );
    700888
    701889        if ( ! $signups = $to_activate['signups'] ) {
     
    779967        }
    780968
    781         $to_delete = self::get( array(
    782             'include' => $signup_ids,
    783         ) );
     969        $to_delete = self::get(
     970            array(
     971                'include' => $signup_ids,
     972            )
     973        );
    784974
    785975        if ( ! $signups = $to_delete['signups'] ) {
Note: See TracChangeset for help on using the changeset viewer.