2009-09-17 20:17:33 +00:00
<? php
/**
2010-01-19 17:08:04 +00:00
* Metadata API
2009-09-17 20:17:33 +00:00
*
2011-12-13 23:45:31 +00:00
* Functions for retrieving and manipulating metadata of various WordPress object types. Metadata
* for an object is a represented by a simple key-value pair. Objects may contain multiple
2010-01-19 17:08:04 +00:00
* metadata entries that share the same key and differ only in their value.
2009-09-17 20:17:33 +00:00
*
* @package WordPress
* @subpackage Meta
* @since 2.9.0
*/
2010-01-19 17:08:04 +00:00
/**
* Add metadata for the specified object.
*
* @since 2.9.0
* @uses $wpdb WordPress database object for queries.
* @uses do_action() Calls 'added_{$meta_type}_meta' with meta_id of added metadata entry,
* object ID, meta key, and meta value
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $object_id ID of the object metadata is for
2010-05-10 20:51:58 +00:00
* @param string $meta_key Metadata key
2010-01-19 17:08:04 +00:00
* @param string $meta_value Metadata value
2011-12-13 23:45:31 +00:00
* @param bool $unique Optional, default is false. Whether the specified metadata key should be
* unique for the object. If true, and the object already has a value for the specified
2010-01-19 17:08:04 +00:00
* metadata key, no change will be made
2011-07-20 22:04:35 +00:00
* @return bool The meta ID on successful update, false on failure.
2010-01-19 17:08:04 +00:00
*/
2009-09-17 20:17:33 +00:00
function add_metadata ( $meta_type , $object_id , $meta_key , $meta_value , $unique = false ) {
if ( ! $meta_type || ! $meta_key )
return false ;
2010-02-23 22:42:54 +00:00
if ( ! $object_id = absint ( $object_id ) )
return false ;
2009-09-17 20:17:33 +00:00
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
global $wpdb ;
$column = esc_sql ( $meta_type . '_id' );
2010-05-10 20:51:58 +00:00
// expected_slashed ($meta_key)
$meta_key = stripslashes ( $meta_key );
2010-10-27 17:45:08 +00:00
$meta_value = stripslashes_deep ( $meta_value );
2011-05-22 23:19:42 +00:00
$meta_value = sanitize_meta ( $meta_key , $meta_value , $meta_type );
2010-05-10 20:51:58 +00:00
2010-10-26 19:11:27 +00:00
$check = apply_filters ( "add_ { $meta_type } _metadata" , null , $object_id , $meta_key , $meta_value , $unique );
if ( null !== $check )
2011-07-20 22:04:35 +00:00
return $check ;
2010-10-26 19:11:27 +00:00
2009-09-17 20:17:33 +00:00
if ( $unique && $wpdb -> get_var ( $wpdb -> prepare (
2009-09-24 17:19:13 +00:00
"SELECT COUNT(*) FROM $table WHERE meta_key = %s AND $column = %d" ,
2009-09-17 20:17:33 +00:00
$meta_key , $object_id ) ) )
return false ;
2010-04-29 19:26:40 +00:00
$_meta_value = $meta_value ;
2010-10-27 17:45:08 +00:00
$meta_value = maybe_serialize ( $meta_value );
2009-09-17 20:17:33 +00:00
2010-10-22 19:18:33 +00:00
do_action ( "add_ { $meta_type } _meta" , $object_id , $meta_key , $_meta_value );
2011-07-20 22:04:35 +00:00
$result = $wpdb -> insert ( $table , array (
2009-09-24 17:19:13 +00:00
$column => $object_id ,
'meta_key' => $meta_key ,
2009-09-17 20:17:33 +00:00
'meta_value' => $meta_value
) );
2011-07-20 22:04:35 +00:00
if ( ! $result )
return false ;
$mid = ( int ) $wpdb -> insert_id ;
2009-09-17 20:17:33 +00:00
wp_cache_delete ( $object_id , $meta_type . '_meta' );
2011-07-20 22:04:35 +00:00
do_action ( "added_ { $meta_type } _meta" , $mid , $object_id , $meta_key , $_meta_value );
2009-09-17 20:17:33 +00:00
2011-07-20 22:04:35 +00:00
return $mid ;
2009-09-17 20:17:33 +00:00
}
2010-01-19 17:08:04 +00:00
/**
2011-12-13 23:45:31 +00:00
* Update metadata for the specified object. If no value already exists for the specified object
2010-01-19 17:08:04 +00:00
* ID and metadata key, the metadata will be added.
*
* @since 2.9.0
* @uses $wpdb WordPress database object for queries.
2010-01-26 22:49:05 +00:00
* @uses do_action() Calls 'update_{$meta_type}_meta' before updating metadata with meta_id of
2010-01-19 17:08:04 +00:00
* metadata entry to update, object ID, meta key, and meta value
2010-01-26 22:49:05 +00:00
* @uses do_action() Calls 'updated_{$meta_type}_meta' after updating metadata with meta_id of
2010-01-19 17:08:04 +00:00
* updated metadata entry, object ID, meta key, and meta value
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $object_id ID of the object metadata is for
2010-05-10 20:51:58 +00:00
* @param string $meta_key Metadata key
2010-01-19 17:08:04 +00:00
* @param string $meta_value Metadata value
2011-12-13 23:45:31 +00:00
* @param string $prev_value Optional. If specified, only update existing metadata entries with
* the specified value. Otherwise, update all entries.
2010-01-19 17:08:04 +00:00
* @return bool True on successful update, false on failure.
*/
2009-09-17 20:17:33 +00:00
function update_metadata ( $meta_type , $object_id , $meta_key , $meta_value , $prev_value = '' ) {
if ( ! $meta_type || ! $meta_key )
return false ;
2010-02-23 22:42:54 +00:00
if ( ! $object_id = absint ( $object_id ) )
return false ;
2009-09-17 20:17:33 +00:00
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
global $wpdb ;
$column = esc_sql ( $meta_type . '_id' );
2009-12-28 16:42:31 +00:00
$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id' ;
2009-09-17 20:17:33 +00:00
2010-05-10 20:51:58 +00:00
// expected_slashed ($meta_key)
$meta_key = stripslashes ( $meta_key );
2011-09-29 19:37:58 +00:00
$passed_value = $meta_value ;
2010-10-27 17:45:08 +00:00
$meta_value = stripslashes_deep ( $meta_value );
2011-05-22 23:19:42 +00:00
$meta_value = sanitize_meta ( $meta_key , $meta_value , $meta_type );
2010-05-10 20:51:58 +00:00
2010-10-26 19:11:27 +00:00
$check = apply_filters ( "update_ { $meta_type } _metadata" , null , $object_id , $meta_key , $meta_value , $prev_value );
if ( null !== $check )
return ( bool ) $check ;
2009-12-28 16:42:31 +00:00
if ( ! $meta_id = $wpdb -> get_var ( $wpdb -> prepare ( "SELECT $id_column FROM $table WHERE meta_key = %s AND $column = %d" , $meta_key , $object_id ) ) )
2011-09-29 19:37:58 +00:00
return add_metadata ( $meta_type , $object_id , $meta_key , $passed_value );
2009-09-17 20:17:33 +00:00
2010-05-11 17:35:07 +00:00
// Compare existing value to new value if no prev value given and the key exists only once.
if ( empty ( $prev_value ) ) {
$old_value = get_metadata ( $meta_type , $object_id , $meta_key );
if ( count ( $old_value ) == 1 ) {
2010-07-12 15:28:31 +00:00
if ( $old_value [ 0 ] === $meta_value )
2010-05-11 17:35:07 +00:00
return false ;
}
}
2010-04-29 19:26:40 +00:00
$_meta_value = $meta_value ;
2010-10-27 17:45:08 +00:00
$meta_value = maybe_serialize ( $meta_value );
2009-09-17 20:17:33 +00:00
$data = compact ( 'meta_value' );
$where = array ( $column => $object_id , 'meta_key' => $meta_key );
if ( ! empty ( $prev_value ) ) {
$prev_value = maybe_serialize ( $prev_value );
$where [ 'meta_value' ] = $prev_value ;
}
2010-04-29 19:26:40 +00:00
do_action ( "update_ { $meta_type } _meta" , $meta_id , $object_id , $meta_key , $_meta_value );
2011-08-24 19:32:59 +00:00
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
2011-08-24 19:32:59 +00:00
do_action ( 'update_postmeta' , $meta_id , $object_id , $meta_key , $meta_value );
2009-09-17 20:17:33 +00:00
$wpdb -> update ( $table , $data , $where );
2011-07-20 22:04:35 +00:00
2009-09-17 20:17:33 +00:00
wp_cache_delete ( $object_id , $meta_type . '_meta' );
2010-04-29 19:26:40 +00:00
do_action ( "updated_ { $meta_type } _meta" , $meta_id , $object_id , $meta_key , $_meta_value );
2011-08-24 19:32:59 +00:00
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
2011-08-24 19:32:59 +00:00
do_action ( 'updated_postmeta' , $meta_id , $object_id , $meta_key , $meta_value );
2009-09-17 20:17:33 +00:00
return true ;
}
2010-01-19 17:08:04 +00:00
/**
* Delete metadata for the specified object.
*
* @since 2.9.0
* @uses $wpdb WordPress database object for queries.
2010-01-26 22:49:05 +00:00
* @uses do_action() Calls 'deleted_{$meta_type}_meta' after deleting with meta_id of
2010-01-19 17:08:04 +00:00
* deleted metadata entries, object ID, meta key, and meta value
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $object_id ID of the object metadata is for
2010-05-10 20:51:58 +00:00
* @param string $meta_key Metadata key
2011-12-13 23:45:31 +00:00
* @param string $meta_value Optional. Metadata value. If specified, only delete metadata entries
* with this value. Otherwise, delete all entries with the specified meta_key.
* @param bool $delete_all Optional, default is false. If true, delete matching metadata entries
* for all objects, ignoring the specified object_id. Otherwise, only delete matching
2010-01-19 17:08:04 +00:00
* metadata entries for the specified object_id.
* @return bool True on successful delete, false on failure.
*/
2009-10-05 01:08:06 +00:00
function delete_metadata ( $meta_type , $object_id , $meta_key , $meta_value = '' , $delete_all = false ) {
2010-02-23 22:42:54 +00:00
if ( ! $meta_type || ! $meta_key )
return false ;
2010-02-28 10:07:55 +00:00
if ( ( ! $object_id = absint ( $object_id )) && ! $delete_all )
2009-09-17 20:17:33 +00:00
return false ;
2009-10-15 20:26:21 +00:00
2009-09-17 20:17:33 +00:00
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
global $wpdb ;
2009-10-06 19:18:21 +00:00
$type_column = esc_sql ( $meta_type . '_id' );
2009-12-28 16:42:31 +00:00
$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id' ;
2010-05-10 20:51:58 +00:00
// expected_slashed ($meta_key)
$meta_key = stripslashes ( $meta_key );
2010-10-27 17:45:08 +00:00
$meta_value = stripslashes_deep ( $meta_value );
2009-09-17 20:17:33 +00:00
2010-10-26 19:11:27 +00:00
$check = apply_filters ( "delete_ { $meta_type } _metadata" , null , $object_id , $meta_key , $meta_value , $delete_all );
if ( null !== $check )
return ( bool ) $check ;
2010-10-27 17:45:08 +00:00
$_meta_value = $meta_value ;
$meta_value = maybe_serialize ( $meta_value );
2011-08-24 19:32:59 +00:00
2009-12-28 16:42:31 +00:00
$query = $wpdb -> prepare ( "SELECT $id_column FROM $table WHERE meta_key = %s" , $meta_key );
2009-09-24 17:19:13 +00:00
2009-10-05 01:08:06 +00:00
if ( ! $delete_all )
2009-10-06 19:18:21 +00:00
$query .= $wpdb -> prepare ( " AND $type_column = %d" , $object_id );
2009-10-05 01:08:06 +00:00
2009-09-17 20:17:33 +00:00
if ( $meta_value )
2009-10-05 01:08:06 +00:00
$query .= $wpdb -> prepare ( " AND meta_value = %s" , $meta_value );
2009-09-24 17:10:28 +00:00
$meta_ids = $wpdb -> get_col ( $query );
if ( ! count ( $meta_ids ) )
return false ;
2011-08-03 16:48:37 +00:00
if ( $delete_all )
$object_ids = $wpdb -> get_col ( $wpdb -> prepare ( "SELECT $type_column FROM $table WHERE meta_key = %s" , $meta_key ) );
2010-10-27 17:45:08 +00:00
do_action ( "delete_ { $meta_type } _meta" , $meta_ids , $object_id , $meta_key , $_meta_value );
2011-08-24 19:32:59 +00:00
2012-04-11 20:02:39 +00:00
// Old-style action.
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
do_action ( 'delete_postmeta' , $meta_ids );
2010-10-22 19:18:33 +00:00
2009-12-28 16:42:31 +00:00
$query = "DELETE FROM $table WHERE $id_column IN( " . implode ( ',' , $meta_ids ) . " )" ;
2009-09-24 17:19:13 +00:00
2009-09-17 20:17:33 +00:00
$count = $wpdb -> query ( $query );
2009-09-24 17:19:13 +00:00
2009-09-17 20:17:33 +00:00
if ( ! $count )
return false ;
2011-08-03 16:48:37 +00:00
if ( $delete_all ) {
foreach ( ( array ) $object_ids as $o_id ) {
wp_cache_delete ( $o_id , $meta_type . '_meta' );
}
} else {
wp_cache_delete ( $object_id , $meta_type . '_meta' );
}
2010-10-27 17:45:08 +00:00
do_action ( "deleted_ { $meta_type } _meta" , $meta_ids , $object_id , $meta_key , $_meta_value );
2011-08-24 19:32:59 +00:00
2012-04-11 20:02:39 +00:00
// Old-style action.
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
do_action ( 'deleted_postmeta' , $meta_ids );
2009-09-17 20:17:33 +00:00
return true ;
}
2010-01-19 17:08:04 +00:00
/**
* Retrieve metadata for the specified object.
*
* @since 2.9.0
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $object_id ID of the object metadata is for
2011-12-13 23:45:31 +00:00
* @param string $meta_key Optional. Metadata key. If not specified, retrieve all metadata for
2010-01-19 17:08:04 +00:00
* the specified object.
2011-12-13 23:45:31 +00:00
* @param bool $single Optional, default is false. If true, return only the first value of the
* specified meta_key. This parameter has no effect if meta_key is not specified.
2010-01-19 17:08:04 +00:00
* @return string|array Single metadata value, or array of values
*/
2009-09-17 20:17:33 +00:00
function get_metadata ( $meta_type , $object_id , $meta_key = '' , $single = false ) {
if ( ! $meta_type )
return false ;
2010-02-23 22:42:54 +00:00
if ( ! $object_id = absint ( $object_id ) )
return false ;
2010-10-26 19:11:27 +00:00
$check = apply_filters ( "get_ { $meta_type } _metadata" , null , $object_id , $meta_key , $single );
if ( null !== $check ) {
2010-10-27 17:45:08 +00:00
if ( $single && is_array ( $check ) )
return $check [ 0 ];
2010-10-26 19:11:27 +00:00
else
2010-10-27 17:45:08 +00:00
return $check ;
2010-10-26 19:11:27 +00:00
}
2009-09-17 20:17:33 +00:00
$meta_cache = wp_cache_get ( $object_id , $meta_type . '_meta' );
if ( ! $meta_cache ) {
2010-11-26 21:35:26 +00:00
$meta_cache = update_meta_cache ( $meta_type , array ( $object_id ) );
$meta_cache = $meta_cache [ $object_id ];
2009-09-17 20:17:33 +00:00
}
2010-10-26 19:11:27 +00:00
if ( ! $meta_key )
2009-09-17 20:17:33 +00:00
return $meta_cache ;
if ( isset ( $meta_cache [ $meta_key ]) ) {
2010-02-23 09:15:47 +00:00
if ( $single )
2009-09-17 20:17:33 +00:00
return maybe_unserialize ( $meta_cache [ $meta_key ][ 0 ] );
2010-02-23 09:15:47 +00:00
else
2009-09-17 20:17:33 +00:00
return array_map ( 'maybe_unserialize' , $meta_cache [ $meta_key ]);
}
2009-09-17 22:11:57 +00:00
if ( $single )
return '' ;
else
return array ();
2009-09-17 20:17:33 +00:00
}
2011-08-24 19:32:59 +00:00
/**
* Determine if a meta key is set for a given object
*
* @since 3.3.0
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $object_id ID of the object metadata is for
2011-10-24 19:13:23 +00:00
* @param string $meta_key Metadata key.
2011-08-24 19:32:59 +00:00
* @return boolean true of the key is set, false if not.
*/
function metadata_exists ( $meta_type , $object_id , $meta_key ) {
if ( ! $meta_type )
return false ;
if ( ! $object_id = absint ( $object_id ) )
return false ;
$check = apply_filters ( "get_ { $meta_type } _metadata" , null , $object_id , $meta_key , true );
if ( null !== $check )
return true ;
$meta_cache = wp_cache_get ( $object_id , $meta_type . '_meta' );
if ( ! $meta_cache ) {
$meta_cache = update_meta_cache ( $meta_type , array ( $object_id ) );
$meta_cache = $meta_cache [ $object_id ];
}
if ( isset ( $meta_cache [ $meta_key ] ) )
return true ;
return false ;
}
2011-07-20 22:04:35 +00:00
/**
* Get meta data by meta ID
*
* @since 3.3.0
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $meta_id ID for a specific meta row
* @return object Meta object or false.
*/
function get_metadata_by_mid ( $meta_type , $meta_id ) {
global $wpdb ;
if ( ! $meta_type )
return false ;
if ( ! $meta_id = absint ( $meta_id ) )
return false ;
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
$id_column = ( 'user' == $meta_type ) ? 'umeta_id' : 'meta_id' ;
$meta = $wpdb -> get_row ( $wpdb -> prepare ( "SELECT * FROM $table WHERE $id_column = %d" , $meta_id ) );
if ( empty ( $meta ) )
return false ;
if ( isset ( $meta -> meta_value ) )
$meta -> meta_value = maybe_unserialize ( $meta -> meta_value );
return $meta ;
}
2011-08-01 17:01:54 +00:00
/**
* Update meta data by meta ID
*
* @since 3.3.0
*
* @uses get_metadata_by_mid() Calls get_metadata_by_mid() to fetch the meta key, value
* and object_id of the given meta_id.
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $meta_id ID for a specific meta row
* @param string $meta_value Metadata value
* @param string $meta_key Optional, you can provide a meta key to update it
* @return bool True on successful update, false on failure.
*/
function update_metadata_by_mid ( $meta_type , $meta_id , $meta_value , $meta_key = false ) {
global $wpdb ;
// Make sure everything is valid.
if ( ! $meta_type )
return false ;
if ( ! $meta_id = absint ( $meta_id ) )
return false ;
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
$column = esc_sql ( $meta_type . '_id' );
$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id' ;
// Fetch the meta and go on if it's found.
if ( $meta = get_metadata_by_mid ( $meta_type , $meta_id ) ) {
$original_key = $meta -> meta_key ;
$original_value = $meta -> meta_value ;
$object_id = $meta -> { $column };
// If a new meta_key (last parameter) was specified, change the meta key,
// otherwise use the original key in the update statement.
if ( false === $meta_key ) {
$meta_key = $original_key ;
} elseif ( ! is_string ( $meta_key ) ) {
return false ;
}
// Sanitize the meta
$_meta_value = $meta_value ;
$meta_value = sanitize_meta ( $meta_key , $meta_value , $meta_type );
$meta_value = maybe_serialize ( $meta_value );
// Format the data query arguments.
$data = array (
'meta_key' => $meta_key ,
'meta_value' => $meta_value
);
// Format the where query arguments.
$where = array ();
$where [ $id_column ] = $meta_id ;
do_action ( "update_ { $meta_type } _meta" , $meta_id , $object_id , $meta_key , $_meta_value );
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
do_action ( 'update_postmeta' , $meta_id , $object_id , $meta_key , $meta_value );
2011-08-24 19:32:59 +00:00
2011-08-01 17:01:54 +00:00
// Run the update query, all fields in $data are %s, $where is a %d.
$result = ( bool ) $wpdb -> update ( $table , $data , $where , '%s' , '%d' );
// Clear the caches.
wp_cache_delete ( $object_id , $meta_type . '_meta' );
do_action ( "updated_ { $meta_type } _meta" , $meta_id , $object_id , $meta_key , $_meta_value );
2011-08-03 16:48:37 +00:00
if ( 'post' == $meta_type )
do_action ( 'updated_postmeta' , $meta_id , $object_id , $meta_key , $meta_value );
2011-08-01 17:01:54 +00:00
return $result ;
}
2011-08-24 19:32:59 +00:00
2011-08-01 17:01:54 +00:00
// And if the meta was not found.
return false ;
}
/**
* Delete meta data by meta ID
*
* @since 3.3.0
*
* @uses get_metadata_by_mid() Calls get_metadata_by_mid() to fetch the meta key, value
* and object_id of the given meta_id.
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int $meta_id ID for a specific meta row
* @return bool True on successful delete, false on failure.
*/
function delete_metadata_by_mid ( $meta_type , $meta_id ) {
global $wpdb ;
2011-08-24 19:32:59 +00:00
2011-08-01 17:01:54 +00:00
// Make sure everything is valid.
if ( ! $meta_type )
return false ;
if ( ! $meta_id = absint ( $meta_id ) )
return false ;
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
2011-08-24 19:32:59 +00:00
2011-08-01 17:01:54 +00:00
// object and id columns
$column = esc_sql ( $meta_type . '_id' );
$id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id' ;
// Fetch the meta and go on if it's found.
if ( $meta = get_metadata_by_mid ( $meta_type , $meta_id ) ) {
$object_id = $meta -> { $column };
do_action ( "delete_ { $meta_type } _meta" , ( array ) $meta_id , $object_id , $meta -> meta_key , $meta -> meta_value );
2012-04-11 20:02:39 +00:00
// Old-style action.
if ( 'post' == $meta_type || 'comment' == $meta_type )
do_action ( "delete_ { $meta_type } meta" , $meta_id );
2011-08-03 16:48:37 +00:00
2011-08-01 17:01:54 +00:00
// Run the query, will return true if deleted, false otherwise
2012-03-24 15:24:31 +00:00
$result = ( bool ) $wpdb -> delete ( $table , array ( $id_column => $meta_id ) );
2011-08-01 17:01:54 +00:00
// Clear the caches.
wp_cache_delete ( $object_id , $meta_type . '_meta' );
2011-08-03 16:48:37 +00:00
2011-08-01 17:01:54 +00:00
do_action ( "deleted_ { $meta_type } _meta" , ( array ) $meta_id , $object_id , $meta -> meta_key , $meta -> meta_value );
2012-04-11 20:02:39 +00:00
// Old-style action.
if ( 'post' == $meta_type || 'comment' == $meta_type )
do_action ( "deleted_ { $meta_type } meta" , $meta_id );
2011-08-03 16:48:37 +00:00
2011-08-01 17:01:54 +00:00
return $result ;
}
2011-08-24 19:32:59 +00:00
2011-08-01 17:01:54 +00:00
// Meta id was not found.
return false ;
}
2010-01-19 17:08:04 +00:00
/**
* Update the metadata cache for the specified objects.
*
* @since 2.9.0
* @uses $wpdb WordPress database object for queries.
*
* @param string $meta_type Type of object metadata is for (e.g., comment, post, or user)
* @param int|array $object_ids array or comma delimited list of object IDs to update cache for
* @return mixed Metadata cache for the specified objects, or false on failure.
*/
2009-09-17 20:17:33 +00:00
function update_meta_cache ( $meta_type , $object_ids ) {
if ( empty ( $meta_type ) || empty ( $object_ids ) )
return false ;
if ( ! $table = _get_meta_table ( $meta_type ) )
return false ;
$column = esc_sql ( $meta_type . '_id' );
global $wpdb ;
if ( ! is_array ( $object_ids ) ) {
$object_ids = preg_replace ( '|[^0-9,]|' , '' , $object_ids );
$object_ids = explode ( ',' , $object_ids );
}
$object_ids = array_map ( 'intval' , $object_ids );
$cache_key = $meta_type . '_meta' ;
$ids = array ();
2010-11-26 21:35:26 +00:00
$cache = array ();
2009-09-17 20:17:33 +00:00
foreach ( $object_ids as $id ) {
2010-11-26 21:35:26 +00:00
$cached_object = wp_cache_get ( $id , $cache_key );
if ( false === $cached_object )
2009-09-17 20:17:33 +00:00
$ids [] = $id ;
2010-11-26 21:35:26 +00:00
else
$cache [ $id ] = $cached_object ;
2009-09-17 20:17:33 +00:00
}
if ( empty ( $ids ) )
2010-11-26 21:35:26 +00:00
return $cache ;
2009-09-17 20:17:33 +00:00
// Get meta info
$id_list = join ( ',' , $ids );
2009-09-24 17:19:13 +00:00
$meta_list = $wpdb -> get_results ( $wpdb -> prepare ( "SELECT $column , meta_key, meta_value FROM $table WHERE $column IN ( $id_list )" ,
2009-09-17 20:17:33 +00:00
$meta_type ), ARRAY_A );
if ( ! empty ( $meta_list ) ) {
foreach ( $meta_list as $metarow ) {
$mpid = intval ( $metarow [ $column ]);
$mkey = $metarow [ 'meta_key' ];
$mval = $metarow [ 'meta_value' ];
// Force subkeys to be array type:
if ( ! isset ( $cache [ $mpid ]) || ! is_array ( $cache [ $mpid ]) )
$cache [ $mpid ] = array ();
if ( ! isset ( $cache [ $mpid ][ $mkey ]) || ! is_array ( $cache [ $mpid ][ $mkey ]) )
$cache [ $mpid ][ $mkey ] = array ();
// Add a value to the current pid/key:
$cache [ $mpid ][ $mkey ][] = $mval ;
}
}
foreach ( $ids as $id ) {
if ( ! isset ( $cache [ $id ]) )
$cache [ $id ] = array ();
2010-11-26 21:35:26 +00:00
wp_cache_add ( $id , $cache [ $id ], $cache_key );
2009-09-17 20:17:33 +00:00
}
return $cache ;
}
2010-12-15 16:51:38 +00:00
/**
2010-11-09 23:22:13 +00:00
* Given a meta query, generates SQL clauses to be appended to a main query
*
2011-04-25 17:27:35 +00:00
* @since 3.2.0
2010-11-09 23:22:13 +00:00
*
2011-04-25 17:27:35 +00:00
* @see WP_Meta_Query
2010-11-09 23:22:13 +00:00
*
2011-09-27 05:13:07 +00:00
* @param array $meta_query A meta query
2011-03-22 20:35:47 +00:00
* @param string $type Type of meta
2010-11-09 23:22:13 +00:00
* @param string $primary_table
* @param string $primary_id_column
2010-11-11 10:06:05 +00:00
* @param object $context (optional) The main query object
2010-11-09 23:22:13 +00:00
* @return array( 'join' => $join_sql, 'where' => $where_sql )
*/
2011-09-27 05:13:07 +00:00
function get_meta_sql ( $meta_query , $type , $primary_table , $primary_id_column , $context = null ) {
2011-04-25 17:27:35 +00:00
$meta_query_obj = new WP_Meta_Query ( $meta_query );
return $meta_query_obj -> get_sql ( $type , $primary_table , $primary_id_column , $context );
}
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
/**
* Container class for a multiple metadata query
*
2011-06-11 04:40:18 +00:00
* @since 3.2.0
2011-04-25 17:27:35 +00:00
*/
class WP_Meta_Query {
/**
* List of metadata queries. A single query is an associative array:
* - 'key' string The meta key
* - 'value' string|array The meta value
* - 'compare' (optional) string How to compare the key to the value.
* Possible values: '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'.
* Default: '='
* - 'type' string (optional) The type of the value.
* Possible values: 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'.
* Default: 'CHAR'
*
2011-06-11 04:40:18 +00:00
* @since 3.2.0
2011-04-25 17:27:35 +00:00
* @access public
* @var array
*/
public $queries = array ();
/**
* The relation between the queries. Can be one of 'AND' or 'OR'.
*
2011-06-11 04:40:18 +00:00
* @since 3.2.0
2011-04-25 17:27:35 +00:00
* @access public
* @var string
2011-06-10 23:01:45 +00:00
*/
2011-04-25 17:27:35 +00:00
public $relation ;
/**
* Constructor
*
2011-09-27 05:13:07 +00:00
* @param array $meta_query (optional) A meta query
2011-04-25 17:27:35 +00:00
*/
function __construct ( $meta_query = false ) {
if ( ! $meta_query )
return ;
if ( isset ( $meta_query [ 'relation' ] ) && strtoupper ( $meta_query [ 'relation' ] ) == 'OR' ) {
$this -> relation = 'OR' ;
} else {
$this -> relation = 'AND' ;
}
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
$this -> queries = array ();
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
foreach ( $meta_query as $key => $query ) {
if ( ! is_array ( $query ) )
continue ;
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
$this -> queries [] = $query ;
}
}
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
/**
* Constructs a meta query based on 'meta_*' query vars
*
2011-06-11 04:40:18 +00:00
* @since 3.2.0
2011-04-25 17:27:35 +00:00
* @access public
*
* @param array $qv The query variables
*/
function parse_query_vars ( $qv ) {
$meta_query = array ();
// Simple query needs to be first for orderby=meta_value to work correctly
foreach ( array ( 'key' , 'compare' , 'type' ) as $key ) {
if ( ! empty ( $qv [ "meta_ $key " ] ) )
$meta_query [ 0 ][ $key ] = $qv [ "meta_ $key " ];
}
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
// WP_Query sets 'meta_value' = '' by default
if ( isset ( $qv [ 'meta_value' ] ) && '' !== $qv [ 'meta_value' ] )
$meta_query [ 0 ][ 'value' ] = $qv [ 'meta_value' ];
2010-11-09 23:22:13 +00:00
2011-04-25 17:27:35 +00:00
if ( ! empty ( $qv [ 'meta_query' ] ) && is_array ( $qv [ 'meta_query' ] ) ) {
$meta_query = array_merge ( $meta_query , $qv [ 'meta_query' ] );
}
2011-04-21 18:13:03 +00:00
2011-04-25 17:27:35 +00:00
$this -> __construct ( $meta_query );
}
2011-04-21 18:13:03 +00:00
2011-04-25 17:27:35 +00:00
/**
* Generates SQL clauses to be appended to a main query.
*
2011-06-11 04:40:18 +00:00
* @since 3.2.0
2011-04-25 17:27:35 +00:00
* @access public
*
* @param string $type Type of meta
* @param string $primary_table
* @param string $primary_id_column
* @param object $context (optional) The main query object
* @return array( 'join' => $join_sql, 'where' => $where_sql )
*/
function get_sql ( $type , $primary_table , $primary_id_column , $context = null ) {
global $wpdb ;
if ( ! $meta_table = _get_meta_table ( $type ) )
return false ;
$meta_id_column = esc_sql ( $type . '_id' );
2011-04-28 15:02:16 +00:00
$join = array ();
2011-04-25 17:27:35 +00:00
$where = array ();
2011-04-28 15:02:16 +00:00
2011-04-25 17:27:35 +00:00
foreach ( $this -> queries as $k => $q ) {
$meta_key = isset ( $q [ 'key' ] ) ? trim ( $q [ 'key' ] ) : '' ;
$meta_type = isset ( $q [ 'type' ] ) ? strtoupper ( $q [ 'type' ] ) : 'CHAR' ;
if ( 'NUMERIC' == $meta_type )
$meta_type = 'SIGNED' ;
elseif ( ! in_array ( $meta_type , array ( 'BINARY' , 'CHAR' , 'DATE' , 'DATETIME' , 'DECIMAL' , 'SIGNED' , 'TIME' , 'UNSIGNED' ) ) )
$meta_type = 'CHAR' ;
2012-06-29 19:59:29 +00:00
$meta_value = isset ( $q [ 'value' ] ) ? $q [ 'value' ] : null ;
if ( isset ( $q [ 'compare' ] ) )
$meta_compare = strtoupper ( $q [ 'compare' ] );
else
$meta_compare = is_array ( $meta_value ) ? 'IN' : '=' ;
if ( ! in_array ( $meta_compare , array (
'=' , '!=' , '>' , '>=' , '<' , '<=' ,
'LIKE' , 'NOT LIKE' ,
'IN' , 'NOT IN' ,
'BETWEEN' , 'NOT BETWEEN' ,
'NOT EXISTS'
) ) )
$meta_compare = '=' ;
2011-04-28 15:02:16 +00:00
$i = count ( $join );
2011-04-25 17:27:35 +00:00
$alias = $i ? 'mt' . $i : $meta_table ;
2010-11-09 23:22:13 +00:00
2012-06-29 19:59:29 +00:00
if ( 'NOT EXISTS' == $meta_compare ) {
$join [ $i ] = "LEFT JOIN $meta_table " ;
$join [ $i ] .= $i ? " AS $alias " : '' ;
$join [ $i ] .= " ON ( $primary_table . $primary_id_column = $alias . $meta_id_column AND $alias .meta_key = ' $meta_key ')" ;
$where [ $k ] = ' ' . $alias . '.' . $meta_id_column . ' IS NULL' ;
continue ;
}
2011-04-28 15:02:16 +00:00
$join [ $i ] = "INNER JOIN $meta_table " ;
$join [ $i ] .= $i ? " AS $alias " : '' ;
$join [ $i ] .= " ON ( $primary_table . $primary_id_column = $alias . $meta_id_column )" ;
2010-11-13 18:32:43 +00:00
2011-04-28 15:02:16 +00:00
$where [ $k ] = '' ;
2011-04-25 17:27:35 +00:00
if ( ! empty ( $meta_key ) )
$where [ $k ] = $wpdb -> prepare ( " $alias .meta_key = %s" , $meta_key );
2010-11-13 18:32:43 +00:00
2012-06-29 19:59:29 +00:00
if ( is_null ( $meta_value ) ) {
2011-04-28 15:02:16 +00:00
if ( empty ( $where [ $k ] ) )
unset ( $join [ $i ] );
2011-04-25 17:27:35 +00:00
continue ;
2011-04-28 15:02:16 +00:00
}
2011-04-25 17:27:35 +00:00
if ( in_array ( $meta_compare , array ( 'IN' , 'NOT IN' , 'BETWEEN' , 'NOT BETWEEN' ) ) ) {
if ( ! is_array ( $meta_value ) )
$meta_value = preg_split ( '/[,\s]+/' , $meta_value );
2011-04-28 15:02:16 +00:00
if ( empty ( $meta_value ) ) {
unset ( $join [ $i ] );
2011-04-25 17:27:35 +00:00
continue ;
2011-04-28 15:02:16 +00:00
}
2011-04-25 17:27:35 +00:00
} else {
$meta_value = trim ( $meta_value );
}
if ( 'IN' == substr ( $meta_compare , - 2 ) ) {
$meta_compare_string = '(' . substr ( str_repeat ( ',%s' , count ( $meta_value ) ), 1 ) . ')' ;
} elseif ( 'BETWEEN' == substr ( $meta_compare , - 7 ) ) {
$meta_value = array_slice ( $meta_value , 0 , 2 );
$meta_compare_string = '%s AND %s' ;
} elseif ( 'LIKE' == substr ( $meta_compare , - 4 ) ) {
$meta_value = '%' . like_escape ( $meta_value ) . '%' ;
$meta_compare_string = '%s' ;
} else {
$meta_compare_string = '%s' ;
}
2011-04-28 15:02:16 +00:00
if ( ! empty ( $where [ $k ] ) )
$where [ $k ] .= ' AND ' ;
$where [ $k ] = ' (' . $where [ $k ] . $wpdb -> prepare ( "CAST( $alias .meta_value AS { $meta_type } ) { $meta_compare } { $meta_compare_string } )" , $meta_value );
2011-04-25 17:27:35 +00:00
}
2011-04-28 15:02:16 +00:00
$where = array_filter ( $where );
if ( empty ( $where ) )
$where = '' ;
else
$where = ' AND (' . implode ( " \n { $this -> relation } " , $where ) . ' )' ;
$join = implode ( " \n " , $join );
if ( ! empty ( $join ) )
$join = ' ' . $join ;
2011-04-21 18:13:03 +00:00
2011-04-25 17:27:35 +00:00
return apply_filters_ref_array ( 'get_meta_sql' , array ( compact ( 'join' , 'where' ), $this -> queries , $type , $primary_table , $primary_id_column , $context ) );
2010-11-13 18:32:43 +00:00
}
}
2010-01-19 17:08:04 +00:00
/**
* Retrieve the name of the metadata table for the specified object type.
*
* @since 2.9.0
* @uses $wpdb WordPress database object for queries.
*
2010-09-07 11:21:11 +00:00
* @param string $type Type of object to get metadata table for (e.g., comment, post, or user)
2010-01-19 17:08:04 +00:00
* @return mixed Metadata table name, or false if no metadata table exists
*/
2009-09-17 20:17:33 +00:00
function _get_meta_table ( $type ) {
global $wpdb ;
$table_name = $type . 'meta' ;
if ( empty ( $wpdb -> $table_name ) )
return false ;
return $wpdb -> $table_name ;
}
2011-05-22 23:19:42 +00:00
/**
* Determine whether a meta key is protected
*
2011-05-25 15:47:17 +00:00
* @since 3.1.3
2011-05-22 23:19:42 +00:00
*
* @param string $meta_key Meta key
* @return bool True if the key is protected, false otherwise.
*/
function is_protected_meta ( $meta_key , $meta_type = null ) {
2011-07-20 22:04:35 +00:00
$protected = ( '_' == $meta_key [ 0 ] );
2011-05-22 23:19:42 +00:00
return apply_filters ( 'is_protected_meta' , $protected , $meta_key , $meta_type );
}
/**
* Sanitize meta value
*
2011-05-25 15:47:17 +00:00
* @since 3.1.3
2011-05-22 23:19:42 +00:00
*
* @param string $meta_key Meta key
* @param mixed $meta_value Meta value to sanitize
* @param string $meta_type Type of meta
* @return mixed Sanitized $meta_value
*/
2011-07-20 22:04:35 +00:00
function sanitize_meta ( $meta_key , $meta_value , $meta_type ) {
return apply_filters ( "sanitize_ { $meta_type } _meta_ { $meta_key } " , $meta_value , $meta_key , $meta_type );
}
/**
* Register meta key
2011-08-24 19:32:59 +00:00
*
2011-07-20 22:04:35 +00:00
* @since 3.3.0
*
* @param string $meta_type Type of meta
* @param string $meta_key Meta key
* @param string|array $sanitize_callback A function or method to call when sanitizing the value of $meta_key.
* @param string|array $auth_callback Optional. A function or method to call when performing edit_post_meta, add_post_meta, and delete_post_meta capability checks.
* @param array $args Arguments
*/
function register_meta ( $meta_type , $meta_key , $sanitize_callback , $auth_callback = null ) {
if ( is_callable ( $sanitize_callback ) )
add_filter ( "sanitize_ { $meta_type } _meta_ { $meta_key } " , $sanitize_callback , 10 , 3 );
if ( empty ( $auth_callback ) ) {
if ( is_protected_meta ( $meta_key , $meta_type ) )
$auth_callback = '__return_false' ;
else
$auth_callback = '__return_true' ;
}
if ( is_callable ( $auth_callback ) )
add_filter ( "auth_ { $meta_type } _meta_ { $meta_key } " , $auth_callback , 10 , 6 );
2011-05-22 23:19:42 +00:00
}