Skip to:
Content

BuddyPress.org

Ticket #6638: 6638.02.patch

File 6638.02.patch, 9.7 KB (added by r-a-y, 9 years ago)
  • src/bp-xprofile/bp-xprofile-cache.php

     
    283283}
    284284add_action( 'update_option_bp-xprofile-fullname-field-name', 'xprofile_clear_fullname_field_id_cache' );
    285285
     286/**
     287 * Clear a field's caches.
     288 *
     289 * @since 2.4.0
     290 *
     291 * @param int|BP_XProfile_Field A field ID or a field object.
     292 * @param bool False on failure.
     293 */
     294function bp_xprofile_clear_field_cache( $field ) {
     295        if ( is_numeric( $field ) ) {
     296                $field_id = (int) $field;
     297        } elseif ( $field instanceof BP_XProfile_Field ) {
     298                $field_id = (int) $field->id;
     299        }
     300
     301        if ( ! isset( $field_id ) ) {
     302                return false;
     303        }
     304
     305        wp_cache_delete( $field_id, 'bp_xprofile_fields' );
     306        wp_cache_delete( $field_id, 'xprofile_meta' );
     307}
     308add_action( 'xprofile_field_after_save', 'bp_xprofile_clear_field_cache' );
     309
    286310// List actions to clear super cached pages on, if super cache is installed.
    287311add_action( 'xprofile_updated_profile', 'bp_core_clear_cache' );
  • src/bp-xprofile/bp-xprofile-functions.php

     
    275275        return $field->save();
    276276}
    277277
    278 function xprofile_get_field( $field_id ) {
    279         return new BP_XProfile_Field( $field_id );
     278/**
     279 * Get a profile field object.
     280 *
     281 * @param int|object $field ID of the field or object representing field data.
     282 * @return BP_XProfile_Field|null Field object if found, otherwise null.
     283 */
     284function xprofile_get_field( $field ) {
     285        if ( $field instanceof BP_XProfile_Field ) {
     286                $_field = $field;
     287        } elseif ( is_object( $field ) ) {
     288                $_field = new BP_XProfile_Field();
     289                $_field->fill_data( $field );
     290        } else {
     291                $_field = BP_XProfile_Field::get_instance( $field );
     292        }
     293
     294        if ( ! $_field ) {
     295                return null;
     296        }
     297
     298        return $_field;
    280299}
    281300
    282301function xprofile_delete_field( $field_id ) {
  • src/bp-xprofile/bp-xprofile-loader.php

     
    393393                wp_cache_add_global_groups( array(
    394394                        'bp_xprofile',
    395395                        'bp_xprofile_data',
     396                        'bp_xprofile_fields',
    396397                        'bp_xprofile_groups',
    397398                        'xprofile_meta'
    398399                ) );
  • src/bp-xprofile/classes/class-bp-xprofile-field.php

     
    211211                $bp    = buddypress();
    212212                $field = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->profile->table_name_fields} WHERE id = %d", $id ) );
    213213
    214                 if ( ! empty( $field ) ) {
    215                         $this->id                = $field->id;
    216                         $this->group_id          = $field->group_id;
    217                         $this->parent_id         = $field->parent_id;
    218                         $this->type              = $field->type;
    219                         $this->name              = stripslashes( $field->name );
    220                         $this->description       = stripslashes( $field->description );
    221                         $this->is_required       = $field->is_required;
    222                         $this->can_delete        = $field->can_delete;
    223                         $this->field_order       = $field->field_order;
    224                         $this->option_order      = $field->option_order;
    225                         $this->order_by          = $field->order_by;
    226                         $this->is_default_option = $field->is_default_option;
    227 
    228                         // Create the field type and store a reference back to this object.
    229                         $this->type_obj            = bp_xprofile_create_field_type( $field->type );
    230                         $this->type_obj->field_obj = $this;
     214                $this->fill_data( $field );
     215
     216                if ( ! empty( $get_data ) && ! empty( $user_id ) ) {
     217                        $this->data = $this->get_field_data( $user_id );
     218                }
     219        }
     220
     221        /**
     222         * Retrieve a `BP_XProfile_Field` instance.
     223         *
     224         * @static
     225         *
     226         * @param int $field_id ID of the field.
     227         * @return BP_XProfile_Field|false Field object if found, otherwise false.
     228         */
     229        public static function get_instance( $field_id ) {
     230                global $wpdb;
     231
     232                $field_id = (int) $field_id;
     233                if ( ! $field_id ) {
     234                        return false;
     235                }
     236
     237                $field = wp_cache_get( $field_id, 'bp_xprofile_fields' );
     238                if ( false === $field ) {
     239                        $bp = buddypress();
     240
     241                        $field = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->profile->table_name_fields} WHERE id = %d", $field_id ) );
     242
     243                        wp_cache_add( $field->id, $field, 'bp_xprofile_fields' );
    231244
    232                         if ( ! empty( $get_data ) && ! empty( $user_id ) ) {
    233                                 $this->data = $this->get_field_data( $user_id );
     245                        if ( ! $field ) {
     246                                return false;
    234247                        }
    235248                }
     249
     250                $_field = new BP_XProfile_Field();
     251                $_field->fill_data( $field );
     252
     253                return $_field;
     254        }
     255
     256        /**
     257         * Fill object vars based on data passed to the method.
     258         *
     259         * @since 2.4.0
     260         *
     261         * @param array|object $args Array or object representing the `BP_XProfile_Field` properties.
     262         *                           Generally, this is a row from the fields database table.
     263         */
     264        public function fill_data( $args ) {
     265                if ( is_object( $args ) ) {
     266                        $args = (array) $args;
     267                }
     268
     269                foreach ( $args as $k => $v ) {
     270                        if ( 'name' === $k || 'description' === $k ) {
     271                                $v = stripslashes( $v );
     272                        }
     273                        $this->{$k} = $v;
     274                }
     275
     276                // Create the field type and store a reference back to this object.
     277                $this->type_obj            = bp_xprofile_create_field_type( $this->type );
     278                $this->type_obj->field_obj = $this;;
    236279        }
    237280
    238281        /**
  • src/bp-xprofile/classes/class-bp-xprofile-group.php

     
    369369                }
    370370
    371371                // Fetch the fields.
    372                 $fields = $wpdb->get_results( "SELECT id, name, description, type, group_id, is_required FROM {$bp->profile->table_name_fields} WHERE group_id IN ( {$group_ids_in} ) AND parent_id = 0 {$exclude_fields_sql} {$in_sql} ORDER BY field_order" );
    373 
    374                 $field_ids = wp_list_pluck( $fields, 'id' );
    375 
    376                 // Store field IDs for meta cache priming.
    377                 $object_ids['field'] = $field_ids;
     372                $field_ids = $wpdb->get_col( "SELECT id FROM {$bp->profile->table_name_fields} WHERE group_id IN ( {$group_ids_in} ) AND parent_id = 0 {$exclude_fields_sql} {$in_sql} ORDER BY field_order" );
    378373
    379374                // Bail if no fields.
    380                 if ( empty( $fields ) ) {
     375                if ( empty( $field_ids ) ) {
    381376                        return $groups;
    382377                }
    383378
     379                $field_ids = array_map( 'intval', $field_ids );
     380
     381                // Prime the field cache.
     382                $uncached_field_ids = bp_get_non_cached_ids( $field_ids, 'bp_xprofile_fields' );
     383                if ( ! empty( $uncached_field_ids ) ) {
     384                        $_uncached_field_ids = implode( ',', array_map( 'intval', $uncached_field_ids ) );
     385                        $uncached_fields = $wpdb->get_results( "SELECT id, name, description, type, group_id, is_required FROM {$bp->profile->table_name_fields} WHERE id IN ({$_uncached_field_ids})" );
     386                        ray_log( 'uncached fields: ' . print_r( $uncached_fields, true ) );
     387                        foreach ( $uncached_fields as $uncached_field ) {
     388                                $fid = intval( $uncached_field->id );
     389                                wp_cache_set( $fid, $uncached_field, 'bp_xprofile_fields' );
     390                        }
     391                }
     392
     393                // Pull field objects from the cache.
     394                $fields = array();
     395                foreach ( $field_ids as $field_id ) {
     396                        $fields[] = xprofile_get_field( $field_id );
     397                }
     398
     399                // Store field IDs for meta cache priming.
     400                $object_ids['field'] = $field_ids;
     401
    384402                // Maybe fetch field data.
    385403                if ( ! empty( $r['fetch_field_data'] ) ) {
    386404
  • tests/phpunit/testcases/xprofile/cache.php

     
    144144                $this->assertFalse( wp_cache_get( $f, 'xprofile_field_meta' ) );
    145145                $this->assertFalse( wp_cache_get( $d->id, 'xprofile_data_meta' ) );
    146146        }
     147
     148        /**
     149         * @ticket BP6638
     150         */
     151        public function test_field_cache_should_be_invalidated_on_save() {
     152                $g = $this->factory->xprofile_group->create();
     153                $f = $this->factory->xprofile_field->create( array(
     154                        'field_group_id' => $g,
     155                        'name' => 'Foo',
     156                ) );
     157
     158                $field = xprofile_get_field( $f );
     159                $this->assertSame( 'Foo', $field->name );
     160
     161                $field->name = 'Bar';
     162                $this->assertNotEmpty( $field->save() );
     163
     164                $field_2 = xprofile_get_field( $f );
     165                $this->assertSame( 'Bar', $field_2->name );
     166        }
    147167}
  • tests/phpunit/testcases/xprofile/functions.php

     
    868868                // assert!
    869869                $this->assertEquals( array( 1, $g1, $g3, $g2 ), wp_list_pluck( $field_groups, 'id' ) );
    870870        }
     871
     872        /**
     873         * @ticket BP6638
     874         */
     875        public function test_xprofile_get_field_should_return_bp_xprofile_field_object() {
     876                global $wpdb;
     877
     878                $g = $this->factory->xprofile_group->create();
     879                $f = $this->factory->xprofile_field->create( array(
     880                        'field_group_id' => $g,
     881                        'type' => 'selectbox',
     882                        'name' => 'Foo',
     883                ) );
     884
     885                $field = xprofile_get_field( $f );
     886
     887                $this->assertTrue( $field instanceof BP_XProfile_Field );
     888        }
     889
     890        /**
     891         * @ticket BP6638
     892         * @group cache
     893         */
     894        public function test_xprofile_get_field_should_prime_field_cache() {
     895                global $wpdb;
     896
     897                $g = $this->factory->xprofile_group->create();
     898                $f = $this->factory->xprofile_field->create( array(
     899                        'field_group_id' => $g,
     900                        'type' => 'selectbox',
     901                        'name' => 'Foo',
     902                ) );
     903
     904                $num_queries = $wpdb->num_queries;
     905
     906                // Prime the cache.
     907                $field_1 = xprofile_get_field( $f );
     908                $num_queries++;
     909                $this->assertSame( $num_queries, $wpdb->num_queries );
     910
     911                // No more queries.
     912                $field_2 = xprofile_get_field( $f );
     913                $this->assertEquals( $field_1, $field_2 );
     914                $this->assertSame( $num_queries, $wpdb->num_queries );
     915        }
    871916}