+/**
+ * Add user meta data as properties to given user object.
+ *
+ * The finished user data is cached, but the cache is not used to fill in the
+ * user data for the given object. Once the function has been used, the cache
+ * should be used to retrieve user data. The intention is if the current data
+ * had been cached already, there would be no need to call this function.
+ *
+ * @access private
+ * @since 2.5.0
+ * @uses $wpdb WordPress database object for queries
+ *
+ * @param object $user The user data object.
+ */
+function _fill_user( &$user ) {
+ $metavalues = get_user_metavalues(array($user->ID));
+ _fill_single_user($user, $metavalues[$user->ID]);
+}
+
+/**
+ * Perform the query to get the $metavalues array(s) needed by _fill_user and _fill_many_users
+ *
+ * @since 3.0.0
+ * @param array $ids User ID numbers list.
+ * @return array of arrays. The array is indexed by user_id, containing $metavalues object arrays.
+ */
+function get_user_metavalues($ids) {
+ global $wpdb;
+
+ $clean = array_map('intval', $ids);
+ if ( 0 == count($clean) )
+ return $objects;
+
+ $list = implode(',', $clean);
+
+ $show = $wpdb->hide_errors();
+ $metavalues = $wpdb->get_results("SELECT user_id, meta_key, meta_value FROM $wpdb->usermeta WHERE user_id IN ($list)");
+ $wpdb->show_errors($show);
+
+ $objects = array();
+ foreach($clean as $id) {
+ $objects[$id] = array();
+ }
+ foreach($metavalues as $meta_object) {
+ $objects[$meta_object->user_id][] = $meta_object;
+ }
+
+ return $objects;
+}
+
+/**
+ * Unserialize user metadata, fill $user object, then cache everything.
+ *
+ * @since 3.0.0
+ * @param object $user The User object.
+ * @param array $metavalues An array of objects provided by get_user_metavalues()
+ */
+function _fill_single_user( &$user, &$metavalues ) {
+ global $wpdb;
+
+ foreach ( $metavalues as $meta ) {
+ $value = maybe_unserialize($meta->meta_value);
+ // Keys used as object vars cannot have dashes.
+ $key = str_replace('-', '', $meta->meta_key);
+ $user->{$key} = $value;
+ }
+
+ $level = $wpdb->prefix . 'user_level';
+ if ( isset( $user->{$level} ) )
+ $user->user_level = $user->{$level};
+
+ // For backwards compat.
+ if ( isset($user->first_name) )
+ $user->user_firstname = $user->first_name;
+ if ( isset($user->last_name) )
+ $user->user_lastname = $user->last_name;
+ if ( isset($user->description) )
+ $user->user_description = $user->description;
+
+ update_user_caches($user);
+}
+
+/**
+ * Take an array of user objects, fill them with metas, and cache them.
+ *
+ * @since 3.0.0
+ * @param array $users User objects
+ */
+function _fill_many_users( &$users ) {
+ $ids = array();
+ foreach($users as $user_object) {
+ $ids[] = $user_object->ID;
+ }
+
+ $metas = get_user_metavalues($ids);
+
+ foreach($users as $user_object) {
+ if (isset($metas[$user_object->ID])) {
+ _fill_single_user($user_object, $metas[$user_object->ID]);
+ }
+ }
+}
+
+/**
+ * Sanitize every user field.
+ *
+ * If the context is 'raw', then the user object or array will get minimal santization of the int fields.
+ *
+ * @since 2.3.0
+ * @uses sanitize_user_field() Used to sanitize the fields.
+ *
+ * @param object|array $user The User Object or Array
+ * @param string $context Optional, default is 'display'. How to sanitize user fields.
+ * @return object|array The now sanitized User Object or Array (will be the same type as $user)
+ */
+function sanitize_user_object($user, $context = 'display') {
+ if ( is_object($user) ) {
+ if ( !isset($user->ID) )
+ $user->ID = 0;
+ if ( isset($user->data) )
+ $vars = get_object_vars( $user->data );
+ else
+ $vars = get_object_vars($user);
+ foreach ( array_keys($vars) as $field ) {
+ if ( is_string($user->$field) || is_numeric($user->$field) )
+ $user->$field = sanitize_user_field($field, $user->$field, $user->ID, $context);
+ }
+ $user->filter = $context;
+ } else {
+ if ( !isset($user['ID']) )
+ $user['ID'] = 0;
+ foreach ( array_keys($user) as $field )
+ $user[$field] = sanitize_user_field($field, $user[$field], $user['ID'], $context);
+ $user['filter'] = $context;
+ }
+
+ return $user;
+}
+
+/**
+ * Sanitize user field based on context.
+ *
+ * Possible context values are: 'raw', 'edit', 'db', 'display', 'attribute' and 'js'. The
+ * 'display' context is used by default. 'attribute' and 'js' contexts are treated like 'display'
+ * when calling filters.
+ *
+ * @since 2.3.0
+ * @uses apply_filters() Calls 'edit_$field' and '${field_no_prefix}_edit_pre' passing $value and
+ * $user_id if $context == 'edit' and field name prefix == 'user_'.
+ *
+ * @uses apply_filters() Calls 'edit_user_$field' passing $value and $user_id if $context == 'db'.
+ * @uses apply_filters() Calls 'pre_$field' passing $value if $context == 'db' and field name prefix == 'user_'.
+ * @uses apply_filters() Calls '${field}_pre' passing $value if $context == 'db' and field name prefix != 'user_'.
+ *
+ * @uses apply_filters() Calls '$field' passing $value, $user_id and $context if $context == anything
+ * other than 'raw', 'edit' and 'db' and field name prefix == 'user_'.
+ * @uses apply_filters() Calls 'user_$field' passing $value if $context == anything other than 'raw',
+ * 'edit' and 'db' and field name prefix != 'user_'.
+ *
+ * @param string $field The user Object field name.
+ * @param mixed $value The user Object value.
+ * @param int $user_id user ID.
+ * @param string $context How to sanitize user fields. Looks for 'raw', 'edit', 'db', 'display',
+ * 'attribute' and 'js'.
+ * @return mixed Sanitized value.
+ */
+function sanitize_user_field($field, $value, $user_id, $context) {
+ $int_fields = array('ID');
+ if ( in_array($field, $int_fields) )
+ $value = (int) $value;
+
+ if ( 'raw' == $context )
+ return $value;
+
+ if ( !is_string($value) && !is_numeric($value) )
+ return $value;
+
+ $prefixed = false;
+ if ( false !== strpos($field, 'user_') ) {
+ $prefixed = true;
+ $field_no_prefix = str_replace('user_', '', $field);
+ }
+
+ if ( 'edit' == $context ) {
+ if ( $prefixed ) {
+ $value = apply_filters("edit_$field", $value, $user_id);
+ } else {
+ $value = apply_filters("edit_user_$field", $value, $user_id);
+ }
+
+ if ( 'description' == $field )
+ $value = esc_html($value);
+ else
+ $value = esc_attr($value);
+ } else if ( 'db' == $context ) {
+ if ( $prefixed ) {
+ $value = apply_filters("pre_$field", $value);
+ } else {
+ $value = apply_filters("pre_user_$field", $value);
+ }
+ } else {
+ // Use display filters by default.
+ if ( $prefixed )
+ $value = apply_filters($field, $value, $user_id, $context);
+ else
+ $value = apply_filters("user_$field", $value, $user_id, $context);
+ }
+
+ if ( 'user_url' == $field )
+ $value = esc_url($value);
+
+ if ( 'attribute' == $context )
+ $value = esc_attr($value);
+ else if ( 'js' == $context )
+ $value = esc_js($value);
+
+ return $value;
+}
+
+/**
+ * Update all user caches
+ *
+ * @since 3.0.0
+ *
+ * @param object $user User object to be cached
+ */
+function update_user_caches(&$user) {
+ wp_cache_add($user->ID, $user, 'users');
+ wp_cache_add($user->user_login, $user->ID, 'userlogins');
+ wp_cache_add($user->user_email, $user->ID, 'useremail');
+ wp_cache_add($user->user_nicename, $user->ID, 'userslugs');
+}
+
+/**
+ * Clean all user caches
+ *
+ * @since 3.0.0
+ *
+ * @param int $id User ID
+ */
+function clean_user_cache($id) {
+ $user = new WP_User($id);
+
+ wp_cache_delete($id, 'users');
+ wp_cache_delete($user->user_login, 'userlogins');
+ wp_cache_delete($user->user_email, 'useremail');
+ wp_cache_delete($user->user_nicename, 'userslugs');
+}
+