Skip to:
Content

BuddyPress.org

Changeset 7862


Ignore:
Timestamp:
02/13/2014 03:50:39 AM (13 years ago)
Author:
boonebgorges
Message:

Migrate xprofilemeta functions to the WP metadata API

The case of XProfile metadata is complex, because xprofile groups, fields, and
data all store their metadata in a single table, differentiated by object_type.
This complication requires additional filters on WP's core metadata queries.

See #4551

Location:
trunk
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/bp-xprofile/bp-xprofile-filters.php

    r7812 r7862  
    262262}
    263263add_filter( 'bp_user_query_populate_extras', 'bp_xprofile_filter_user_query_populate_extras', 2, 2 );
     264
     265/**
     266 * Filter meta queries to modify for the xprofile data schema.
     267 *
     268 * @since BuddyPress (2.0.0)
     269 *
     270 * @access private Do not use.
     271 *
     272 * @param string $q SQL query.
     273 * @return string
     274 */
     275function bp_xprofile_filter_meta_query( $q ) {
     276        global $wpdb;
     277
     278        // Get the first word of the command
     279        preg_match( '/^(\S+)/', $q, $first_word_matches );
     280
     281        if ( empty( $first_word_matches[0] ) ) {
     282                return $q;
     283        }
     284
     285        // Get the field type
     286        preg_match( '/xprofile_(group|field|data)_id/', $q, $matches );
     287
     288        if ( empty( $matches[0] ) || empty( $matches[1] ) ) {
     289                return $q;
     290        }
     291
     292        switch ( $first_word_matches[0] ) {
     293
     294                /**
     295                 * SELECT:
     296                 * - replace 'xprofile_{fieldtype}_id' with 'object_id'
     297                 * - ensure that 'object_id' is aliased to 'xprofile_{fieldtype}_id',
     298                 *   because update_meta_cache() needs the column name to parse
     299                 *   the query results
     300                 * - append the 'object type' WHERE clause
     301                 */
     302                case 'SELECT' :
     303                        $q = str_replace(
     304                                array(
     305                                        $matches[0],
     306                                        'SELECT object_id',
     307                                        'WHERE ',
     308                                ),
     309                                array(
     310                                        'object_id',
     311                                        'SELECT object_id AS ' . $matches[0],
     312                                        $wpdb->prepare( 'WHERE object_type = %s AND ', $matches[1] ),
     313                                ),
     314                                $q
     315                        );
     316                        break;
     317
     318                /**
     319                 * UPDATE and DELETE:
     320                 * - replace 'xprofile_{fieldtype}_id' with 'object_id'
     321                 * - append the 'object type' WHERE clause
     322                 */
     323                case 'UPDATE' :
     324                case 'DELETE' :
     325                        $q = str_replace(
     326                                array(
     327                                        $matches[0],
     328                                        'WHERE ',
     329                                ),
     330                                array(
     331                                        'object_id',
     332                                        $wpdb->prepare( 'WHERE object_type = %s AND ', $matches[1] ),
     333                                ),
     334                                $q
     335                        );
     336                        break;
     337
     338                /**
     339                 * UPDATE and DELETE:
     340                 * - replace 'xprofile_{fieldtype}_id' with 'object_id'
     341                 * - ensure that the object_type field gets filled in
     342                 */
     343                case 'INSERT' :
     344                        $q = str_replace(
     345                                array(
     346                                        '`' . $matches[0] . '`',
     347                                        'VALUES (',
     348                                ),
     349                                array(
     350                                        '`object_type`,`object_id`',
     351                                        $wpdb->prepare( "VALUES (%s,", $matches[1] ),
     352                                ),
     353                                $q
     354                        );
     355                        break;
     356        }
     357
     358        return $q;
     359}
  • trunk/bp-xprofile/bp-xprofile-functions.php

    r7836 r7862  
    530530/*** XProfile Meta ****************************************************/
    531531
     532/**
     533 * Delete a piece of xprofile metadata.
     534 *
     535 * @param int $object_id ID of the object the metadata belongs to.
     536 * @param string $object_type Type of object. 'group', 'field', or 'data'.
     537 * @param string $meta_key Key of the metadata being deleted. If omitted, all
     538 *        metadata for the object will be deleted.
     539 * @param mixed $meta_value Optional. If provided, only metadata that matches
     540 *        the value will be permitted.
     541 * @return bool True on success, false on failure.
     542 */
    532543function bp_xprofile_delete_meta( $object_id, $object_type, $meta_key = false, $meta_value = false ) {
    533         global $wpdb, $bp;
    534 
    535         $object_id = (int) $object_id;
    536 
    537         if ( !$object_id )
    538                 return false;
    539 
    540         if ( !isset( $object_type ) )
    541                 return false;
    542 
    543         if ( !in_array( $object_type, array( 'group', 'field', 'data' ) ) )
    544                 return false;
    545 
     544        global $wpdb;
     545
     546        // Legacy - no empty object id
     547        if ( empty( $object_id ) ) {
     548                return false;
     549        }
     550
     551        // Legacy - sanitize object type
     552        if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
     553                return false;
     554        }
     555
     556        // Legacy - if no meta_key is passed, delete all for the item
     557        if ( empty( $meta_key ) ) {
     558                $table_key  = 'xprofile_' . $object_type . 'meta';
     559                $table_name = $wpdb->{$table_key};
     560                $keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$table_name} WHERE object_type = %s AND object_id = %d", $object_type, $object_id ) );
     561        } else {
     562                $keys = array( $meta_key );
     563        }
     564
     565        // Legacy - trim meta_value
     566        $meta_value = trim( $meta_value );
     567
     568        add_filter( 'query', 'bp_filter_metaid_column_name' );
     569        add_filter( 'query', 'bp_xprofile_filter_meta_query' );
     570
     571        foreach ( $keys as $key ) {
     572                $retval = delete_metadata( 'xprofile_' . $object_type, $object_id, $key, $meta_value );
     573        }
     574
     575        remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
     576        remove_filter( 'query', 'bp_filter_metaid_column_name' );
     577
     578        return $retval;
     579}
     580
     581/**
     582 * Get a piece of xprofile metadata.
     583 *
     584 * @param int $object_id ID of the object the metadata belongs to.
     585 * @param string $object_type Type of object. 'group', 'field', or 'data'.
     586 * @param string $meta_key Key of the metadata being fetched. If omitted, all
     587 *        metadata for the object will be retrieved.
     588 * @return mixed Meta value if found. False on failure.
     589 */
     590function bp_xprofile_get_meta( $object_id, $object_type, $meta_key = '') {
     591        // Legacy - sanitize object type
     592        if ( ! in_array( $object_type, array( 'group', 'field', 'data' ) ) ) {
     593                return false;
     594        }
     595
     596        add_filter( 'query', 'bp_filter_metaid_column_name' );
     597        add_filter( 'query', 'bp_xprofile_filter_meta_query' );
     598        $retval = get_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, true );
     599        remove_filter( 'query', 'bp_filter_metaid_column_name' );
     600        remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
     601
     602        // Legacy - if no meta_key is provided, return just the located
     603        // values (not a structured array)
     604        if ( empty( $meta_key ) && ! empty( $retval ) ) {
     605                $values = array();
     606                foreach ( $retval as $v ) {
     607                        $values[] = array_pop( $v );
     608                }
     609
     610                $retval = $values;
     611        }
     612
     613        return $retval;
     614}
     615
     616/**
     617 * Update a piece of xprofile metadata.
     618 *
     619 * @param int $object_id ID of the object the metadata belongs to.
     620 * @param string $object_type Type of object. 'group', 'field', or 'data'.
     621 * @param string $meta_key Key of the metadata being updated.
     622 * @param mixed $meta_value Value of the metadata being updated.
     623 * @return bool True on success, false on failure.
     624 */
     625function bp_xprofile_update_meta( $object_id, $object_type, $meta_key, $meta_value ) {
     626
     627        // Legacy - sanitize meta_key
    546628        $meta_key = preg_replace( '|[^a-z0-9_]|i', '', $meta_key );
    547629
    548         if ( is_array( $meta_value ) || is_object( $meta_value ) ) {
    549                 $meta_value = serialize( $meta_value );
    550         }
    551 
    552         $meta_value = trim( $meta_value );
    553 
    554         if ( empty( $meta_key ) ) {
    555                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s", $object_id, $object_type ) );
    556         } elseif ( !empty( $meta_value ) ) {
    557                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s AND meta_key = %s AND meta_value = %s", $object_id, $object_type, $meta_key, $meta_value ) );
    558         } else {
    559                 $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s AND meta_key = %s", $object_id, $object_type, $meta_key ) );
    560         }
    561 
    562         // Delete the cached object
    563         wp_cache_delete( 'bp_xprofile_meta_' . $object_type . '_' . $object_id . '_' . $meta_key, 'bp' );
    564 
    565         return true;
    566 }
    567 
    568 function bp_xprofile_get_meta( $object_id, $object_type, $meta_key = '') {
    569         global $wpdb, $bp;
    570 
    571         $object_id = (int) $object_id;
    572 
    573         if ( !$object_id )
    574                 return false;
    575 
    576         if ( !isset( $object_type ) )
    577                 return false;
    578 
    579         if ( !in_array( $object_type, array( 'group', 'field', 'data' ) ) )
    580                 return false;
    581 
    582         if ( !empty( $meta_key ) ) {
    583                 $meta_key = preg_replace( '|[^a-z0-9_]|i', '', $meta_key );
    584 
    585                 if ( !$metas = wp_cache_get( 'bp_xprofile_meta_' . $object_type . '_' . $object_id . '_' . $meta_key, 'bp' ) ) {
    586                         $metas = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s AND meta_key = %s", $object_id, $object_type, $meta_key ) );
    587                         wp_cache_set( 'bp_xprofile_meta_' . $object_type . '_' . $object_id . '_' . $meta_key, $metas, 'bp' );
    588                 }
    589         } else {
    590                 $metas = $wpdb->get_col( $wpdb->prepare( "SELECT meta_value FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s", $object_id, $object_type ) );
    591         }
    592 
    593         if ( empty( $metas ) ) {
    594                 if ( empty( $meta_key ) ) {
    595                         return array();
    596                 } else {
    597                         return '';
    598                 }
    599         }
    600 
    601         $metas = array_map( 'maybe_unserialize', (array) $metas );
    602 
    603         if ( 1 == count( $metas ) )
    604                 return $metas[0];
    605         else
    606                 return $metas;
    607 }
    608 
    609 function bp_xprofile_update_meta( $object_id, $object_type, $meta_key, $meta_value ) {
    610         global $wpdb, $bp;
    611 
    612         $object_id = (int) $object_id;
    613 
    614         if ( empty( $object_id ) )
    615                 return false;
    616 
    617         if ( !isset( $object_type ) )
    618                 return false;
    619 
    620         if ( !in_array( $object_type, array( 'group', 'field', 'data' ) ) )
    621                 return false;
    622 
    623         $meta_key = preg_replace( '|[^a-z0-9_]|i', '', $meta_key );
    624 
    625         if ( is_string( $meta_value ) ) {
    626                 $meta_value = stripslashes( $meta_value );
    627         }
    628 
    629         $meta_value = maybe_serialize( $meta_value );
    630 
    631         if ( empty( $meta_value ) )
    632                 return bp_xprofile_delete_meta( $object_id, $object_type, $meta_key );
    633 
    634         $cur = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->profile->table_name_meta} WHERE object_id = %d AND object_type = %s AND meta_key = %s", $object_id, $object_type, $meta_key ) );
    635 
    636         if ( empty( $cur ) )
    637                 $wpdb->query( $wpdb->prepare( "INSERT INTO {$bp->profile->table_name_meta} ( object_id, object_type, meta_key, meta_value ) VALUES ( %d, %s, %s, %s )", $object_id, $object_type,  $meta_key, $meta_value ) );
    638         else if ( $cur->meta_value != $meta_value )
    639                 $wpdb->query( $wpdb->prepare( "UPDATE {$bp->profile->table_name_meta} SET meta_value = %s WHERE object_id = %d AND object_type = %s AND meta_key = %s", $meta_value, $object_id, $object_type, $meta_key ) );
    640         else
    641                 return false;
    642 
    643         // Update the cached object and recache
    644         wp_cache_set( 'bp_xprofile_meta_' . $object_type . '_' . $object_id . '_' . $meta_key, $meta_value, 'bp' );
    645 
    646         return true;
     630        add_filter( 'query', 'bp_filter_metaid_column_name' );
     631        add_filter( 'query', 'bp_xprofile_filter_meta_query' );
     632        $retval = update_metadata( 'xprofile_' . $object_type, $object_id, $meta_key, $meta_value );
     633        remove_filter( 'query', 'bp_xprofile_filter_meta_query' );
     634        remove_filter( 'query', 'bp_filter_metaid_column_name' );
     635
     636        // Legacy - if we fall through to add_metadata(), return true rather
     637        // than the integer meta_id
     638        if ( is_int( $retval ) ) {
     639                $retval = (bool) $retval;
     640        }
     641
     642        return $retval;
    647643}
    648644
  • trunk/bp-xprofile/bp-xprofile-loader.php

    r7756 r7862  
    139139                );
    140140
     141                $meta_tables = array(
     142                        'xprofile_group' => $bp->table_prefix . 'bp_xprofile_meta',
     143                        'xprofile_field' => $bp->table_prefix . 'bp_xprofile_meta',
     144                        'xprofile_data'  => $bp->table_prefix . 'bp_xprofile_meta',
     145                );
     146
    141147                $globals = array(
    142148                        'slug'                  => BP_XPROFILE_SLUG,
    143149                        'has_directory'         => false,
    144150                        'notification_callback' => 'xprofile_format_notifications',
    145                         'global_tables'         => $global_tables
     151                        'global_tables'         => $global_tables,
     152                        'meta_tables'           => $meta_tables,
    146153                );
    147154
  • trunk/tests/testcases/xprofile/functions.php

    r7856 r7862  
    235235
    236236                // These will fail because of a caching bug
    237                 //$this->assertEquals( '', bp_xprofile_get_meta( $g->id, 'group', 'foo' ) );
    238                 //$this->assertEquals( '', bp_xprofile_get_meta( $g->id, 'group', 'foo2' ) );
     237                $this->assertEquals( '', bp_xprofile_get_meta( $g->id, 'group', 'foo' ) );
     238                $this->assertEquals( '', bp_xprofile_get_meta( $g->id, 'group', 'foo2' ) );
    239239        }
    240240
Note: See TracChangeset for help on using the changeset viewer.