WP_Users

The BuddyPress WP Users class.

Defined (1)

The class is defined in the following location(s).

/bp-forums/bbpress/bb-includes/backpress/class.wp-users.php  
  1. class WP_Users { 
  2. var $db; 
  3.  
  4. function WP_Users( &$db ) { 
  5. $this->__construct( $db ); 
  6. // register_shutdown_function( array(&$this, '__destruct') ); 
  7.  
  8. function __construct( &$db ) { 
  9. $this->db =& $db; 
  10.  
  11. // function __destruct() { 
  12. // } 
  13.  
  14. function _put_user( $args = null ) { 
  15. $defaults = array( 
  16. 'ID' => false,  
  17. 'user_login' => '',  
  18. 'user_nicename' => '',  
  19. 'user_email' => '',  
  20. 'user_url' => '',  
  21. 'user_pass' => false,  
  22. 'user_registered' => time(),  
  23. 'display_name' => '',  
  24. 'user_status' => 0,  
  25. 'strict_user_login' => true 
  26. ); 
  27.  
  28. $fields = array_keys( wp_parse_args( $args ) ); 
  29. $args = wp_parse_args( $args, $defaults ); 
  30. unset($defaults['strict_user_login']); 
  31.  
  32. if ( isset($args['ID']) && $args['ID'] ) { 
  33. unset($defaults['ID']); 
  34. $fields = array_intersect( $fields, array_keys( $defaults ) ); 
  35. } else { 
  36. $fields = array_keys( $defaults ); 
  37.  
  38. extract( $args, EXTR_SKIP ); 
  39.  
  40. $ID = (int) $ID; 
  41.  
  42. if ( !$ID || in_array( 'user_login', $fields ) ) { 
  43. $user_login = $this->sanitize_user( $user_login, $strict_user_login ); 
  44.  
  45. if ( !$user_login ) 
  46. return new WP_Error( 'user_login', __('Invalid login name') ); 
  47. if ( !$ID && $this->get_user( $user_login, array( 'by' => 'login' ) ) ) 
  48. return new WP_Error( 'user_login', __('Name already exists') ); 
  49.  
  50. if ( !$ID || in_array( 'user_nicename', $fields ) ) { 
  51. if ( !$user_nicename = $this->sanitize_nicename( $user_nicename ? $user_nicename : $user_login ) ) 
  52. return new WP_Error( 'user_nicename', __('Invalid nicename') ); 
  53. if ( !$ID && $this->get_user( $user_nicename, array( 'by' => 'nicename' ) ) ) 
  54. return new WP_Error( 'user_nicename', __('Nicename already exists') ); 
  55.  
  56. if ( !$ID || in_array( 'user_email', $fields ) ) { 
  57. if ( !$this->is_email( $user_email ) ) 
  58. return new WP_Error( 'user_email', __('Invalid email address') ); 
  59.  
  60. if ( $already_email = $this->get_user( $user_email, array( 'by' => 'email' ) ) ) { 
  61. // if new user, or if multiple users with that email, or if only one user with that email, but it's not the user being updated 
  62. if ( !$ID || is_wp_error( $already_email ) || $already_email->ID != $ID ) 
  63. return new WP_Error( 'user_email', __('Email already exists') ); 
  64.  
  65. if ( !$ID || in_array( 'user_url', $fields ) ) { 
  66. $user_url = esc_url( $user_url ); 
  67.  
  68. if ( !$ID || in_array( 'user_pass', $fields ) ) { 
  69. if ( !$user_pass ) 
  70. $user_pass = WP_Pass::generate_password(); 
  71. $plain_pass = $user_pass; 
  72. $user_pass = WP_Pass::hash_password( $user_pass ); 
  73.  
  74. if ( !$ID || in_array( 'user_registered', $fields ) ) { 
  75. if ( !is_numeric($user_registered) ) 
  76. $user_registered = backpress_gmt_strtotime( $user_registered ); 
  77.  
  78. if ( !$user_registered || $user_registered < 0 ) 
  79. return new WP_Error( 'user_registered', __('Invalid registration time') ); 
  80.  
  81. if ( !$user_registered = @gmdate('Y-m-d H:i:s', $user_registered) ) 
  82. return new WP_Error( 'user_registered', __('Invalid registration timestamp') ); 
  83.  
  84. if ( !$ID || in_array( 'user_display', $fields ) ) { 
  85. if ( !$display_name ) 
  86. $display_name = $user_login; 
  87.  
  88. $db_return = NULL; 
  89. if ( $ID ) { 
  90. $db_return = $this->db->update( $this->db->users, compact( $fields ), compact('ID') ); 
  91. } else { 
  92. $db_return = $this->db->insert( $this->db->users, compact( $fields ) ); 
  93. $ID = $this->db->insert_id; 
  94.  
  95. if ( !$db_return ) 
  96. return new WP_Error( 'WP_Users::_put_user', __('Query failed') ); 
  97.  
  98. // Cache the result 
  99. if ( $ID ) { 
  100. wp_cache_delete( $ID, 'users' ); 
  101. $this->get_user( $ID, array( 'from_cache' => false ) ); 
  102.  
  103. $args = compact( array_keys($args) ); 
  104. $args['plain_pass'] = $plain_pass; 
  105.  
  106. do_action( __CLASS__ . '::' . __FUNCTION__, $args ); 
  107.  
  108. return $args; 
  109.  
  110. function new_user( $args = null ) { 
  111. $args = wp_parse_args( $args ); 
  112. $args['ID'] = false; 
  113.  
  114. $r = $this->_put_user( $args ); 
  115.  
  116. if ( is_wp_error($r) ) 
  117. return $r; 
  118.  
  119. do_action( __CLASS__ . '::' . __FUNCTION__, $r, $args ); 
  120.  
  121. return $r; 
  122.  
  123. function update_user( $ID, $args = null ) { 
  124. $args = wp_parse_args( $args ); 
  125.  
  126. $args['output'] = OBJECT; 
  127. $user = $this->get_user( $ID, $args ); 
  128. if ( !$user || is_wp_error( $user ) ) 
  129. return $user; 
  130.  
  131. $args['ID'] = $user->ID; 
  132.  
  133. $r = $this->_put_user( $args ); 
  134.  
  135. if ( is_wp_error($r) ) 
  136. return $r; 
  137.  
  138. do_action( __CLASS__ . '::' . __FUNCTION__, $r, $args ); 
  139.  
  140. return $r; 
  141.  
  142. /** 
  143. * set_password() - Updates the user's password with a new encrypted one 
  144. * For integration with other applications, this function can be 
  145. * overwritten to instead use the other package password checking 
  146. * algorithm. 
  147. * @since 2.5 
  148. * @uses WP_Pass::hash_password() Used to encrypt the user's password before passing to the database 
  149. * @param string $password The plaintext new user password 
  150. * @param int $user_id User ID 
  151. */ 
  152. function set_password( $password, $user_id ) { 
  153. $user = $this->get_user( $user_id ); 
  154. if ( !$user || is_wp_error( $user ) ) 
  155. return $user; 
  156.  
  157. $user_id = $user->ID; 
  158. $hash = WP_Pass::hash_password($password); 
  159. $this->update_user( $user->ID, array( 'user_pass' => $password ) ); 
  160.  
  161. // $user_id can be user ID#, user_login, user_email (by specifying by = email) 
  162. function get_user( $user_id = 0, $args = null ) { 
  163. $defaults = array( 'output' => OBJECT, 'by' => false, 'from_cache' => true, 'append_meta' => true ); 
  164. $args = wp_parse_args( $args, $defaults ); 
  165. extract( $args, EXTR_SKIP ); 
  166.  
  167. if ( !$user_id ) { 
  168. return false; 
  169.  
  170. // Let's just deal with arrays 
  171. $user_ids = (array) $user_id; 
  172.  
  173. if ( !count( $user_ids ) ) { 
  174. return false; 
  175.  
  176. // Validate passed ids 
  177. $safe_user_ids = array(); 
  178. foreach ( $user_ids as $_user_id ) { 
  179. switch ( $by ) { 
  180. case 'login': 
  181. $safe_user_ids[] = $this->sanitize_user( $_user_id, true ); 
  182. break; 
  183. case 'email': 
  184. if ( $this->is_email( $_user_id ) ) { 
  185. $safe_user_ids[] = $_user_id; 
  186. break; 
  187. case 'nicename': 
  188. $safe_user_ids[] = $this->sanitize_nicename( $_user_id ); 
  189. break; 
  190. default: 
  191. if ( is_numeric( $_user_id ) ) { 
  192. $safe_user_ids[] = (int) $_user_id; 
  193. } else { // If one $_user_id is non-numerical, treat all $user_ids as user_logins 
  194. $safe_user_ids[] = $this->sanitize_user( $_user_id, true ); 
  195. $by = 'login'; 
  196. break; 
  197.  
  198. // No soup for you! 
  199. if ( !count( $safe_user_ids ) ) { 
  200. return false; 
  201.  
  202. // Name the cache storing non-existant ids and the SQL field to query by 
  203. switch ( $by ) { 
  204. case 'login': 
  205. $non_existant_cache = 'userlogins'; 
  206. $sql_field = 'user_login'; 
  207. break; 
  208. case 'email': 
  209. $non_existant_cache = 'useremail'; 
  210. $sql_field = 'user_email'; 
  211. break; 
  212. case 'nicename': 
  213. $non_existant_cache = 'usernicename'; 
  214. $sql_field = 'user_nicename'; 
  215. break; 
  216. default: 
  217. $non_existant_cache = 'users'; 
  218. $sql_field = 'ID'; 
  219. break; 
  220.  
  221. // Check if the numeric user IDs exist from caches 
  222. $cached_users = array(); 
  223. if ( $from_cache ) { 
  224. $existant_user_ids = array(); 
  225. $maybe_existant_user_ids = array(); 
  226.  
  227. switch ( $by ) { 
  228. case 'login': 
  229. case 'email': 
  230. case 'nicename': 
  231. foreach ( $safe_user_ids as $_safe_user_id ) { 
  232. $ID = wp_cache_get( $_safe_user_id, $non_existant_cache ); 
  233. if ( false === $ID ) { 
  234. $maybe_existant_user_ids[] = $_safe_user_id; 
  235. } elseif ( 0 !== $ID ) { 
  236. $existant_user_ids[] = $ID; 
  237. if ( count( $existant_user_ids ) ) { 
  238. // We need to run again using numeric ids 
  239. $args['by'] = false; 
  240. $cached_users = $this->get_user( $existant_user_ids, $args ); 
  241. break; 
  242. default: 
  243. foreach ( $safe_user_ids as $_safe_user_id ) { 
  244. $user = wp_cache_get( $_safe_user_id, 'users' ); 
  245. if ( false === $user ) { 
  246. $maybe_existant_user_ids[] = $_safe_user_id; 
  247. } elseif ( 0 !== $user ) { 
  248. $cached_users[] = $user; 
  249. break; 
  250.  
  251. // No maybes? Then it's definite. 
  252. if ( !count( $maybe_existant_user_ids ) ) { 
  253. if ( !count( $cached_users ) ) { 
  254. // Nothing there sorry 
  255. return false; 
  256.  
  257. // Deal with the case where one record was requested but multiple records are returned 
  258. if ( !is_array( $user_id ) && $user_id ) { 
  259. if ( 1 < count( $cached_users ) ) { 
  260. if ( 'user_email' == $sql_field ) { 
  261. $err = __( 'Multiple email matches. Log in with your username.' ); 
  262. } else { 
  263. $err = sprintf( __( 'Multiple %s matches' ), $sql_field ); 
  264. return new WP_Error( $sql_field, $err, $args + array( 'user_id' => $user_id, 'unique' => false ) ); 
  265.  
  266. // If one item was requested, it expects a single user object back 
  267. $cached_users = array_shift( $cached_users ); 
  268.  
  269. backpress_convert_object( $cached_users, $output ); 
  270. return $cached_users; 
  271.  
  272. // If we get this far, there are some maybes so try and grab them 
  273. } else { 
  274. $maybe_existant_user_ids = $safe_user_ids; 
  275.  
  276. // Escape the ids for the SQL query 
  277. $maybe_existant_user_ids = $this->db->escape_deep( $maybe_existant_user_ids ); 
  278.  
  279. // Sort the ids so the MySQL will more consistently cache the query 
  280. sort( $maybe_existant_user_ids ); 
  281.  
  282. // Get the users from the database 
  283. $sql = "SELECT * FROM `{$this->db->users}` WHERE `$sql_field` in ('" . join( "', '", $maybe_existant_user_ids ) . "');"; 
  284. $db_users = $this->db->get_results( $sql ); 
  285.  
  286. // Merge in the cached users if available 
  287. if ( count( $cached_users ) ) { 
  288. // Create a convenient array of database fetched user ids 
  289. $db_user_ids = array(); 
  290. foreach ( $db_users as $_db_user ) { 
  291. $db_user_ids[] = $_db_user->ID; 
  292. $users = array_merge( $cached_users, $db_users ); 
  293. } else { 
  294. $users = $db_users; 
  295.  
  296. // Deal with the case where one record was requested but multiple records are returned 
  297. if ( !is_array( $user_id ) && $user_id ) { 
  298. if ( 1 < count( $users ) ) { 
  299. if ( 'user_email' == $sql_field ) { 
  300. $err = __( 'Multiple email matches. Log in with your username.' ); 
  301. } else { 
  302. $err = sprintf( __( 'Multiple %s matches' ), $sql_field ); 
  303. return new WP_Error( $sql_field, $err, $args + array( 'user_id' => $user_id, 'unique' => false ) ); 
  304.  
  305. // Create a convenient array of final user ids 
  306. $final_user_ids = array(); 
  307. foreach ( $users as $_user ) { 
  308. $final_user_ids[] = $_user->$sql_field; 
  309.  
  310. foreach ( $safe_user_ids as $_safe_user_id ) { 
  311. if ( !in_array( $_safe_user_id, $final_user_ids ) ) { 
  312. wp_cache_add( $_safe_user_id, 0, $non_existant_cache ); 
  313.  
  314. if ( !count( $users ) ) { 
  315. return false; 
  316.  
  317. // Add display names 
  318. $final_users = array(); 
  319. foreach ( $users as $_user ) { 
  320. // Make sure there is a display_name set 
  321. if ( !$_user->display_name ) { 
  322. $_user->display_name = $_user->user_login; 
  323.  
  324. $final_users[] = $_user; 
  325.  
  326. // append_meta() does the user object, useremail, userlogins caching 
  327. if ( $append_meta ) { 
  328. if ( count( $cached_users ) ) { 
  329. $db_final_users =array(); 
  330. $cached_final_users = array(); 
  331. foreach ( $final_users as $final_user ) { 
  332. if ( in_array( $final_user->ID, $db_user_ids ) ) { 
  333. $db_final_users[] = $final_user; 
  334. } else { 
  335. $cached_final_users[] = $final_user; 
  336. $db_final_users = $this->append_meta( $db_final_users ); 
  337. $final_users = array_merge( $cached_final_users, $db_final_users ); 
  338. } else { 
  339. $final_users = $this->append_meta( $final_users ); 
  340.  
  341. // If one item was requested, it expects a single user object back 
  342. if ( !is_array( $user_id ) && $user_id ) { 
  343. $final_users = array_shift( $final_users ); 
  344.  
  345. backpress_convert_object( $final_users, $output ); 
  346. return $final_users; 
  347.  
  348. function delete_user( $user_id ) { 
  349. $user = $this->get_user( $user_id ); 
  350.  
  351. if ( !$user || is_wp_error( $user ) ) 
  352. return $user; 
  353.  
  354. do_action( 'pre_' . __CLASS__ . '::' . __FUNCTION__, $user->ID ); 
  355.  
  356. $r = $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->users} WHERE ID = %d", $user->ID ) ); 
  357. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->usermeta} WHERE user_id = %d", $user->ID ) ); 
  358.  
  359. wp_cache_delete( $user->ID, 'users' ); 
  360. wp_cache_delete( $user->user_nicename, 'usernicename' ); 
  361. wp_cache_delete( $user->user_email, 'useremail' ); 
  362. wp_cache_delete( $user->user_login, 'userlogins' ); 
  363.  
  364. do_action( __CLASS__ . '::' . __FUNCTION__, $user->ID ); 
  365.  
  366. return $r; 
  367.  
  368. // Used for user meta, but can be used for other meta data (such as bbPress' topic meta) 
  369. // Should this be in the class or should it be it's own special function? 
  370. function append_meta( $object, $args = null ) { 
  371. $defaults = array( 'meta_table' => 'usermeta', 'meta_field' => 'user_id', 'id_field' => 'ID', 'cache_group' => 'users' ); 
  372. $args = wp_parse_args( $args, $defaults ); 
  373. extract( $args, EXTR_SKIP ); 
  374.  
  375. if ( is_array($object) ) { 
  376. $trans = array(); 
  377. foreach ( array_keys($object) as $i ) 
  378. $trans[$object[$i]->$id_field] =& $object[$i]; 
  379. $ids = join(', ', array_keys($trans)); 
  380. if ( $ids && $metas = $this->db->get_results("SELECT $meta_field, meta_key, meta_value FROM {$this->db->$meta_table} WHERE $meta_field IN ($ids) /* WP_Users::append_meta */") ) { 
  381. usort( $metas, array(&$this, '_append_meta_sort') ); 
  382. foreach ( $metas as $meta ) { 
  383. if ( empty( $meta->meta_key ) ) 
  384. continue; 
  385. $trans[$meta->$meta_field]->{$meta->meta_key} = maybe_unserialize( $meta->meta_value ); 
  386. if ( strpos($meta->meta_key, $this->db->prefix) === 0 ) 
  387. $trans[$meta->$meta_field]->{substr($meta->meta_key, strlen($this->db->prefix))} = maybe_unserialize( $meta->meta_value ); 
  388. foreach ( array_keys($trans) as $i ) { 
  389. wp_cache_set( $i, $trans[$i], $cache_group ); 
  390. if ( 'users' == $cache_group ) { 
  391. wp_cache_set( $trans[$i]->user_login, $i, 'userlogins' ); 
  392. wp_cache_set( $trans[$i]->user_email, $i, 'useremail' ); 
  393. wp_cache_set( $trans[$i]->user_nicename, $i, 'usernicename' ); 
  394. return $object; 
  395. } elseif ( $object ) { 
  396. if ( $metas = $this->db->get_results("SELECT meta_key, meta_value FROM {$this->db->$meta_table} WHERE $meta_field = '{$object->$id_field}' /* WP_Users::append_meta */") ) { 
  397. usort( $metas, array(&$this, '_append_meta_sort') ); 
  398. foreach ( $metas as $meta ) { 
  399. if ( empty( $meta->meta_key ) ) 
  400. continue; 
  401. $object->{$meta->meta_key} = maybe_unserialize( $meta->meta_value ); 
  402. if ( strpos($meta->meta_key, $this->db->prefix) === 0 ) 
  403. $object->{substr($meta->meta_key, strlen($this->db->prefix))} = maybe_unserialize( $meta->meta_value ); 
  404. wp_cache_set( $object->$id_field, $object, $cache_group ); 
  405. if ( 'users' == $cache_group ) { 
  406. wp_cache_set($object->user_login, $object->ID, 'userlogins'); 
  407. wp_cache_set($object->user_email, $object->ID, 'useremail'); 
  408. wp_cache_set($object->user_nicename, $object->ID, 'usernicename'); 
  409. return $object; 
  410.  
  411. /**  
  412. * _append_meta_sort() - sorts meta keys by length to ensure $appended_object->{$bbdb->prefix}key overwrites $appended_object->key as desired 
  413. * @internal 
  414. */ 
  415. function _append_meta_sort( $a, $b ) { 
  416. return strlen( $a->meta_key ) - strlen( $b->meta_key ); 
  417.  
  418. function update_meta( $args = null ) { 
  419. $defaults = array( 'id' => 0, 'meta_key' => null, 'meta_value' => null, 'meta_table' => 'usermeta', 'meta_field' => 'user_id', 'cache_group' => 'users' ); 
  420. $args = wp_parse_args( $args, $defaults ); 
  421. extract( $args, EXTR_SKIP ); 
  422.  
  423. $user = $this->get_user( $id ); 
  424. if ( !$user || is_wp_error($user) ) 
  425. return $user; 
  426.  
  427. $id = (int) $user->ID; 
  428.  
  429. if ( is_null($meta_key) || is_null($meta_value) ) 
  430. return false; 
  431.  
  432. $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); 
  433. if ( 'usermeta' == $meta_table && 'capabilities' == $meta_key ) 
  434. $meta_key = $this->db->prefix . 'capabilities'; 
  435.  
  436. $meta_tuple = compact('id', 'meta_key', 'meta_value', 'meta_table'); 
  437. $meta_tuple = apply_filters( __CLASS__ . '::' . __FUNCTION__, $meta_tuple ); 
  438. extract($meta_tuple, EXTR_OVERWRITE); 
  439.  
  440. $_meta_value = maybe_serialize( $meta_value ); 
  441.  
  442. $cur = $this->db->get_row( $this->db->prepare( "SELECT * FROM {$this->db->$meta_table} WHERE $meta_field = %d AND meta_key = %s", $id, $meta_key ) ); 
  443.  
  444. if ( !$cur ) { 
  445. $this->db->insert( $this->db->$meta_table, array( $meta_field => $id, 'meta_key' => $meta_key, 'meta_value' => $_meta_value ) ); 
  446. } elseif ( $cur->meta_value != $meta_value ) { 
  447. $this->db->update( $this->db->$meta_table, array( 'meta_value' => $_meta_value ), array( $meta_field => $id, 'meta_key' => $meta_key ) ); 
  448.  
  449.  
  450. wp_cache_delete( $id, $cache_group ); 
  451.  
  452. return true; 
  453.  
  454. function delete_meta( $args = null ) { 
  455. $defaults = array( 'id' => 0, 'meta_key' => null, 'meta_value' => null, 'meta_table' => 'usermeta', 'meta_field' => 'user_id', 'meta_id_field' => 'umeta_id', 'cache_group' => 'users' ); 
  456. $args = wp_parse_args( $args, $defaults ); 
  457. extract( $args, EXTR_SKIP ); 
  458.  
  459. $user = $this->get_user( $id ); 
  460. if ( !$user || is_wp_error($user) ) 
  461. return $user; 
  462.  
  463. $id = (int) $id; 
  464.  
  465. if ( is_null($meta_key) ) 
  466. return false; 
  467.  
  468. $meta_key = preg_replace('|[^a-z0-9_]|i', '', $meta_key); 
  469.  
  470. $meta_tuple = compact('id', 'meta_key', 'meta_value', 'meta_table'); 
  471. $meta_tuple = apply_filters( __CLASS__ . '::' . __FUNCTION__, $meta_tuple ); 
  472. extract($meta_tuple, EXTR_OVERWRITE); 
  473.  
  474. $_meta_value = is_null($meta_value) ? null : maybe_serialize( $meta_value ); 
  475.  
  476. if ( is_null($_meta_value) ) 
  477. $meta_id = $this->db->get_var( $this->db->prepare( "SELECT $meta_id_field FROM {$this->db->$meta_table} WHERE $meta_field = %d AND meta_key = %s", $id, $meta_key ) ); 
  478. else 
  479. $meta_id = $this->db->get_var( $this->db->prepare( "SELECT $meta_id_field FROM {$this->db->$meta_table} WHERE $meta_field = %d AND meta_key = %s AND meta_value = %s", $id, $meta_key, $_meta_value ) ); 
  480.  
  481. if ( !$meta_id ) 
  482. return false; 
  483.  
  484. if ( is_null($_meta_value) ) 
  485. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->$meta_table} WHERE $meta_field = %d AND meta_key = %s", $id, $meta_key ) ); 
  486. else 
  487. $this->db->query( $this->db->prepare( "DELETE FROM {$this->db->$meta_table} WHERE $meta_id_field = %d", $meta_id ) ); 
  488.  
  489. wp_cache_delete( $id, $cache_group ); 
  490.  
  491. return true; 
  492.  
  493. function sanitize_user( $user_login, $strict = false ) { 
  494. return sanitize_user( $user_login, $strict ); 
  495.  
  496. function sanitize_nicename( $slug ) { 
  497. return sanitize_title( $slug ); 
  498.  
  499. function is_email( $email ) { 
  500. return is_email( $email ); 
  501.