Wordpress 2.7.1
[autoinstalls/wordpress.git] / wp-admin / includes / user.php
1 <?php
2 /**
3  * WordPress user administration API.
4  *
5  * @package WordPress
6  * @subpackage Administration
7  */
8
9 /**
10  * Creates a new user from the "Users" form using $_POST information.
11  *
12  * {@internal Missing Long Description}}
13  *
14  * @since unknown
15  *
16  * @param int $user_id Optional. User ID.
17  * @return null|WP_Error|int Null when adding user, WP_Error or User ID integer when no parameters.
18  */
19 function add_user() {
20         if ( func_num_args() ) { // The hackiest hack that ever did hack
21                 global $current_user, $wp_roles;
22                 $user_id = (int) func_get_arg( 0 );
23
24                 if ( isset( $_POST['role'] ) ) {
25                         if( $user_id != $current_user->id || $wp_roles->role_objects[$_POST['role']]->has_cap( 'edit_users' ) ) {
26                                 $user = new WP_User( $user_id );
27                                 $user->set_role( $_POST['role'] );
28                         }
29                 }
30         } else {
31                 add_action( 'user_register', 'add_user' ); // See above
32                 return edit_user();
33         }
34 }
35
36 /**
37  * {@internal Missing Short Description}}
38  *
39  * {@internal Missing Long Description}}
40  *
41  * @since unknown
42  *
43  * @param int $user_id Optional. User ID.
44  * @return unknown
45  */
46 function edit_user( $user_id = 0 ) {
47         global $current_user, $wp_roles, $wpdb;
48         if ( $user_id != 0 ) {
49                 $update = true;
50                 $user->ID = (int) $user_id;
51                 $userdata = get_userdata( $user_id );
52                 $user->user_login = $wpdb->escape( $userdata->user_login );
53         } else {
54                 $update = false;
55                 $user = '';
56         }
57
58         if ( isset( $_POST['user_login'] ))
59                 $user->user_login = wp_specialchars( trim( $_POST['user_login'] ));
60
61         $pass1 = $pass2 = '';
62         if ( isset( $_POST['pass1'] ))
63                 $pass1 = $_POST['pass1'];
64         if ( isset( $_POST['pass2'] ))
65                 $pass2 = $_POST['pass2'];
66
67         if ( isset( $_POST['role'] ) && current_user_can( 'edit_users' ) ) {
68                 if( $user_id != $current_user->id || $wp_roles->role_objects[$_POST['role']]->has_cap( 'edit_users' ))
69                         $user->role = $_POST['role'];
70         }
71
72         if ( isset( $_POST['email'] ))
73                 $user->user_email = wp_specialchars( trim( $_POST['email'] ));
74         if ( isset( $_POST['url'] ) ) {
75                 $user->user_url = clean_url( trim( $_POST['url'] ));
76                 $user->user_url = preg_match('/^(https?|ftps?|mailto|news|irc|gopher|nntp|feed|telnet):/is', $user->user_url) ? $user->user_url : 'http://'.$user->user_url;
77         }
78         if ( isset( $_POST['first_name'] ))
79                 $user->first_name = wp_specialchars( trim( $_POST['first_name'] ));
80         if ( isset( $_POST['last_name'] ))
81                 $user->last_name = wp_specialchars( trim( $_POST['last_name'] ));
82         if ( isset( $_POST['nickname'] ))
83                 $user->nickname = wp_specialchars( trim( $_POST['nickname'] ));
84         if ( isset( $_POST['display_name'] ))
85                 $user->display_name = wp_specialchars( trim( $_POST['display_name'] ));
86         if ( isset( $_POST['description'] ))
87                 $user->description = trim( $_POST['description'] );
88         if ( isset( $_POST['jabber'] ))
89                 $user->jabber = wp_specialchars( trim( $_POST['jabber'] ));
90         if ( isset( $_POST['aim'] ))
91                 $user->aim = wp_specialchars( trim( $_POST['aim'] ));
92         if ( isset( $_POST['yim'] ))
93                 $user->yim = wp_specialchars( trim( $_POST['yim'] ));
94         if ( !$update )
95                 $user->rich_editing = 'true';  // Default to true for new users.
96         else if ( isset( $_POST['rich_editing'] ) )
97                 $user->rich_editing = $_POST['rich_editing'];
98         else
99                 $user->rich_editing = 'true';
100
101         $user->comment_shortcuts = isset( $_POST['comment_shortcuts'] )? $_POST['comment_shortcuts'] : '';
102
103         $user->use_ssl = 0;
104         if ( !empty($_POST['use_ssl']) )
105                 $user->use_ssl = 1;
106
107         if ( !$update )
108                 $user->admin_color = 'fresh';  // Default to fresh for new users.
109         else if ( isset( $_POST['admin_color'] ) )
110                 $user->admin_color = $_POST['admin_color'];
111         else
112                 $user->admin_color = 'fresh';
113
114         $errors = new WP_Error();
115
116         /* checking that username has been typed */
117         if ( $user->user_login == '' )
118                 $errors->add( 'user_login', __( '<strong>ERROR</strong>: Please enter a username.' ));
119
120         /* checking the password has been typed twice */
121         do_action_ref_array( 'check_passwords', array ( $user->user_login, & $pass1, & $pass2 ));
122
123         if ( $update ) {
124                 if ( empty($pass1) && !empty($pass2) )
125                         $errors->add( 'pass', __( '<strong>ERROR</strong>: You entered your new password only once.' ), array( 'form-field' => 'pass1' ) );
126                 elseif ( !empty($pass1) && empty($pass2) )
127                         $errors->add( 'pass', __( '<strong>ERROR</strong>: You entered your new password only once.' ), array( 'form-field' => 'pass2' ) );
128         } else {
129                 if ( empty($pass1) )
130                         $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter your password.' ), array( 'form-field' => 'pass1' ) );
131                 elseif ( empty($pass2) )
132                         $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter your password twice.' ), array( 'form-field' => 'pass2' ) );
133         }
134
135         /* Check for "\" in password */
136         if( strpos( " ".$pass1, "\\" ) )
137                 $errors->add( 'pass', __( '<strong>ERROR</strong>: Passwords may not contain the character "\\".' ), array( 'form-field' => 'pass1' ) );
138
139         /* checking the password has been typed twice the same */
140         if ( $pass1 != $pass2 )
141                 $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter the same password in the two password fields.' ), array( 'form-field' => 'pass1' ) );
142
143         if (!empty ( $pass1 ))
144                 $user->user_pass = $pass1;
145
146         if ( !$update && !validate_username( $user->user_login ) )
147                 $errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is invalid. Please enter a valid username.' ));
148
149         if (!$update && username_exists( $user->user_login ))
150                 $errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ));
151
152         /* checking e-mail address */
153         if ( empty ( $user->user_email ) ) {
154                 $errors->add( 'user_email', __( '<strong>ERROR</strong>: Please enter an e-mail address.' ), array( 'form-field' => 'email' ) );
155         } else
156                 if (!is_email( $user->user_email ) ) {
157                         $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );
158                 }
159
160         if ( $errors->get_error_codes() )
161                 return $errors;
162
163         if ( $update ) {
164                 $user_id = wp_update_user( get_object_vars( $user ));
165         } else {
166                 $user_id = wp_insert_user( get_object_vars( $user ));
167                 wp_new_user_notification( $user_id );
168         }
169         return $user_id;
170 }
171
172 /**
173  * {@internal Missing Short Description}}
174  *
175  * {@internal Missing Long Description}}
176  *
177  * @since unknown
178  *
179  * @return array List of user IDs.
180  */
181 function get_author_user_ids() {
182         global $wpdb;
183         $level_key = $wpdb->prefix . 'user_level';
184         return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value != '0'", $level_key) );
185 }
186
187 /**
188  * {@internal Missing Short Description}}
189  *
190  * {@internal Missing Long Description}}
191  *
192  * @since unknown
193  *
194  * @param int $user_id User ID.
195  * @return array|bool List of editable authors. False if no editable users.
196  */
197 function get_editable_authors( $user_id ) {
198         global $wpdb;
199
200         $editable = get_editable_user_ids( $user_id );
201
202         if( !$editable ) {
203                 return false;
204         } else {
205                 $editable = join(',', $editable);
206                 $authors = $wpdb->get_results( "SELECT * FROM $wpdb->users WHERE ID IN ($editable) ORDER BY display_name" );
207         }
208
209         return apply_filters('get_editable_authors', $authors);
210 }
211
212 /**
213  * {@internal Missing Short Description}}
214  *
215  * {@internal Missing Long Description}}
216  *
217  * @since unknown
218  *
219  * @param int $user_id User ID.
220  * @param bool $exclude_zeros Optional, default is true. Whether to exclude zeros.
221  * @return unknown
222  */
223 function get_editable_user_ids( $user_id, $exclude_zeros = true, $post_type = 'post' ) {
224         global $wpdb;
225
226         $user = new WP_User( $user_id );
227
228         if ( ! $user->has_cap("edit_others_{$post_type}s") ) {
229                 if ( $user->has_cap("edit_{$post_type}s") || $exclude_zeros == false )
230                         return array($user->id);
231                 else
232                         return false;
233         }
234
235         $level_key = $wpdb->prefix . 'user_level';
236
237         $query = $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s", $level_key);
238         if ( $exclude_zeros )
239                 $query .= " AND meta_value != '0'";
240
241         return $wpdb->get_col( $query );
242 }
243
244 /**
245  * {@internal Missing Short Description}}
246  *
247  * {@internal Missing Long Description}}
248  *
249  * @since unknown
250  *
251  * @return unknown
252  */
253 function get_nonauthor_user_ids() {
254         global $wpdb;
255         $level_key = $wpdb->prefix . 'user_level';
256
257         return $wpdb->get_col( $wpdb->prepare("SELECT user_id FROM $wpdb->usermeta WHERE meta_key = %s AND meta_value = '0'", $level_key) );
258 }
259
260 /**
261  * Retrieve editable posts from other users.
262  *
263  * @since unknown
264  *
265  * @param int $user_id User ID to not retrieve posts from.
266  * @param string $type Optional, defaults to 'any'. Post type to retrieve, can be 'draft' or 'pending'.
267  * @return array List of posts from others.
268  */
269 function get_others_unpublished_posts($user_id, $type='any') {
270         global $wpdb;
271
272         $editable = get_editable_user_ids( $user_id );
273
274         if ( in_array($type, array('draft', 'pending')) )
275                 $type_sql = " post_status = '$type' ";
276         else
277                 $type_sql = " ( post_status = 'draft' OR post_status = 'pending' ) ";
278
279         $dir = ( 'pending' == $type ) ? 'ASC' : 'DESC';
280
281         if( !$editable ) {
282                 $other_unpubs = '';
283         } else {
284                 $editable = join(',', $editable);
285                 $other_unpubs = $wpdb->get_results( $wpdb->prepare("SELECT ID, post_title, post_author FROM $wpdb->posts WHERE post_type = 'post' AND $type_sql AND post_author IN ($editable) AND post_author != %d ORDER BY post_modified $dir", $user_id) );
286         }
287
288         return apply_filters('get_others_drafts', $other_unpubs);
289 }
290
291 /**
292  * Retrieve drafts from other users.
293  *
294  * @since unknown
295  *
296  * @param int $user_id User ID.
297  * @return array List of drafts from other users.
298  */
299 function get_others_drafts($user_id) {
300         return get_others_unpublished_posts($user_id, 'draft');
301 }
302
303 /**
304  * Retrieve pending review posts from other users.
305  *
306  * @since unknown
307  *
308  * @param int $user_id User ID.
309  * @return array List of posts with pending review post type from other users.
310  */
311 function get_others_pending($user_id) {
312         return get_others_unpublished_posts($user_id, 'pending');
313 }
314
315 /**
316  * Retrieve user data and filter it.
317  *
318  * @since unknown
319  *
320  * @param int $user_id User ID.
321  * @return object WP_User object with user data.
322  */
323 function get_user_to_edit( $user_id ) {
324         $user = new WP_User( $user_id );
325         $user->user_login   = attribute_escape($user->user_login);
326         $user->user_email   = attribute_escape($user->user_email);
327         $user->user_url     = clean_url($user->user_url);
328         $user->first_name   = attribute_escape($user->first_name);
329         $user->last_name    = attribute_escape($user->last_name);
330         $user->display_name = attribute_escape($user->display_name);
331         $user->nickname     = attribute_escape($user->nickname);
332         $user->aim          = isset( $user->aim ) && !empty( $user->aim ) ? attribute_escape($user->aim) : '';
333         $user->yim          = isset( $user->yim ) && !empty( $user->yim ) ? attribute_escape($user->yim) : '';
334         $user->jabber       = isset( $user->jabber ) && !empty( $user->jabber ) ? attribute_escape($user->jabber) : '';
335         $user->description  = isset( $user->description ) && !empty( $user->description ) ? wp_specialchars($user->description) : '';
336
337         return $user;
338 }
339
340 /**
341  * Retrieve the user's drafts.
342  *
343  * @since unknown
344  *
345  * @param int $user_id User ID.
346  * @return array
347  */
348 function get_users_drafts( $user_id ) {
349         global $wpdb;
350         $query = $wpdb->prepare("SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'draft' AND post_author = %d ORDER BY post_modified DESC", $user_id);
351         $query = apply_filters('get_users_drafts', $query);
352         return $wpdb->get_results( $query );
353 }
354
355 /**
356  * Remove user and optionally reassign posts and links to another user.
357  *
358  * If the $reassign parameter is not assigned to an User ID, then all posts will
359  * be deleted of that user. The action 'delete_user' that is passed the User ID
360  * being deleted will be run after the posts are either reassigned or deleted.
361  * The user meta will also be deleted that are for that User ID.
362  *
363  * @since unknown
364  *
365  * @param int $id User ID.
366  * @param int $reassign Optional. Reassign posts and links to new User ID.
367  * @return bool True when finished.
368  */
369 function wp_delete_user($id, $reassign = 'novalue') {
370         global $wpdb;
371
372         $id = (int) $id;
373
374         if ($reassign == 'novalue') {
375                 $post_ids = $wpdb->get_col( $wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id) );
376
377                 if ($post_ids) {
378                         foreach ($post_ids as $post_id)
379                                 wp_delete_post($post_id);
380                 }
381
382                 // Clean links
383                 $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->links WHERE link_owner = %d", $id) );
384         } else {
385                 $reassign = (int) $reassign;
386                 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET post_author = %d WHERE post_author = %d", $reassign, $id) );
387                 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->links SET link_owner = %d WHERE link_owner = %d", $reassign, $id) );
388         }
389
390         // FINALLY, delete user
391         do_action('delete_user', $id);
392
393         $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->users WHERE ID = %d", $id) );
394         $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->usermeta WHERE user_id = %d", $id) );
395
396         wp_cache_delete($id, 'users');
397         wp_cache_delete($user->user_login, 'userlogins');
398         wp_cache_delete($user->user_email, 'useremail');
399
400         return true;
401 }
402
403 /**
404  * Remove all capabilities from user.
405  *
406  * @since unknown
407  *
408  * @param int $id User ID.
409  */
410 function wp_revoke_user($id) {
411         $id = (int) $id;
412
413         $user = new WP_User($id);
414         $user->remove_all_caps();
415 }
416
417 if ( !class_exists('WP_User_Search') ) :
418 /**
419  * WordPress User Search class.
420  *
421  * @since unknown
422  * @author Mark Jaquith
423  */
424 class WP_User_Search {
425
426         /**
427          * {@internal Missing Description}}
428          *
429          * @since unknown
430          * @access private
431          * @var unknown_type
432          */
433         var $results;
434
435         /**
436          * {@internal Missing Description}}
437          *
438          * @since unknown
439          * @access private
440          * @var unknown_type
441          */
442         var $search_term;
443
444         /**
445          * Page number.
446          *
447          * @since unknown
448          * @access private
449          * @var int
450          */
451         var $page;
452
453         /**
454          * Role name that users have.
455          *
456          * @since unknown
457          * @access private
458          * @var string
459          */
460         var $role;
461
462         /**
463          * Raw page number.
464          *
465          * @since unknown
466          * @access private
467          * @var int|bool
468          */
469         var $raw_page;
470
471         /**
472          * Amount of users to display per page.
473          *
474          * @since unknown
475          * @access public
476          * @var int
477          */
478         var $users_per_page = 50;
479
480         /**
481          * {@internal Missing Description}}
482          *
483          * @since unknown
484          * @access private
485          * @var unknown_type
486          */
487         var $first_user;
488
489         /**
490          * {@internal Missing Description}}
491          *
492          * @since unknown
493          * @access private
494          * @var int
495          */
496         var $last_user;
497
498         /**
499          * {@internal Missing Description}}
500          *
501          * @since unknown
502          * @access private
503          * @var unknown_type
504          */
505         var $query_limit;
506
507         /**
508          * {@internal Missing Description}}
509          *
510          * @since unknown
511          * @access private
512          * @var unknown_type
513          */
514         var $query_sort;
515
516         /**
517          * {@internal Missing Description}}
518          *
519          * @since unknown
520          * @access private
521          * @var unknown_type
522          */
523         var $query_from_where;
524
525         /**
526          * {@internal Missing Description}}
527          *
528          * @since unknown
529          * @access private
530          * @var int
531          */
532         var $total_users_for_query = 0;
533
534         /**
535          * {@internal Missing Description}}
536          *
537          * @since unknown
538          * @access private
539          * @var bool
540          */
541         var $too_many_total_users = false;
542
543         /**
544          * {@internal Missing Description}}
545          *
546          * @since unknown
547          * @access private
548          * @var unknown_type
549          */
550         var $search_errors;
551
552         /**
553          * {@internal Missing Description}}
554          *
555          * @since unknown
556          * @access private
557          * @var unknown_type
558          */
559         var $paging_text;
560
561         /**
562          * PHP4 Constructor - Sets up the object properties.
563          *
564          * @since unknown
565          *
566          * @param string $search_term Search terms string.
567          * @param int $page Optional. Page ID.
568          * @param string $role Role name.
569          * @return WP_User_Search
570          */
571         function WP_User_Search ($search_term = '', $page = '', $role = '') {
572                 $this->search_term = $search_term;
573                 $this->raw_page = ( '' == $page ) ? false : (int) $page;
574                 $this->page = (int) ( '' == $page ) ? 1 : $page;
575                 $this->role = $role;
576
577                 $this->prepare_query();
578                 $this->query();
579                 $this->prepare_vars_for_template_usage();
580                 $this->do_paging();
581         }
582
583         /**
584          * {@internal Missing Short Description}}
585          *
586          * {@internal Missing Long Description}}
587          *
588          * @since unknown
589          * @access public
590          */
591         function prepare_query() {
592                 global $wpdb;
593                 $this->first_user = ($this->page - 1) * $this->users_per_page;
594                 $this->query_limit = $wpdb->prepare(" LIMIT %d, %d", $this->first_user, $this->users_per_page);
595                 $this->query_sort = ' ORDER BY user_login';
596                 $search_sql = '';
597                 if ( $this->search_term ) {
598                         $searches = array();
599                         $search_sql = 'AND (';
600                         foreach ( array('user_login', 'user_nicename', 'user_email', 'user_url', 'display_name') as $col )
601                                 $searches[] = $col . " LIKE '%$this->search_term%'";
602                         $search_sql .= implode(' OR ', $searches);
603                         $search_sql .= ')';
604                 }
605
606                 $this->query_from_where = "FROM $wpdb->users";
607                 if ( $this->role )
608                         $this->query_from_where .= $wpdb->prepare(" INNER JOIN $wpdb->usermeta ON $wpdb->users.ID = $wpdb->usermeta.user_id WHERE $wpdb->usermeta.meta_key = '{$wpdb->prefix}capabilities' AND $wpdb->usermeta.meta_value LIKE %s", '%' . $this->role . '%');
609                 else
610                         $this->query_from_where .= " WHERE 1=1";
611                 $this->query_from_where .= " $search_sql";
612
613         }
614
615         /**
616          * {@internal Missing Short Description}}
617          *
618          * {@internal Missing Long Description}}
619          *
620          * @since unknown
621          * @access public
622          */
623         function query() {
624                 global $wpdb;
625                 $this->results = $wpdb->get_col('SELECT ID ' . $this->query_from_where . $this->query_sort . $this->query_limit);
626
627                 if ( $this->results )
628                         $this->total_users_for_query = $wpdb->get_var('SELECT COUNT(ID) ' . $this->query_from_where); // no limit
629                 else
630                         $this->search_errors = new WP_Error('no_matching_users_found', __('No matching users were found!'));
631         }
632
633         /**
634          * {@internal Missing Short Description}}
635          *
636          * {@internal Missing Long Description}}
637          *
638          * @since unknown
639          * @access public
640          */
641         function prepare_vars_for_template_usage() {
642                 $this->search_term = stripslashes($this->search_term); // done with DB, from now on we want slashes gone
643         }
644
645         /**
646          * {@internal Missing Short Description}}
647          *
648          * {@internal Missing Long Description}}
649          *
650          * @since unknown
651          * @access public
652          */
653         function do_paging() {
654                 if ( $this->total_users_for_query > $this->users_per_page ) { // have to page the results
655                         $args = array();
656                         if( ! empty($this->search_term) )
657                                 $args['usersearch'] = urlencode($this->search_term);
658                         if( ! empty($this->role) )
659                                 $args['role'] = urlencode($this->role);
660
661                         $this->paging_text = paginate_links( array(
662                                 'total' => ceil($this->total_users_for_query / $this->users_per_page),
663                                 'current' => $this->page,
664                                 'base' => 'users.php?%_%',
665                                 'format' => 'userspage=%#%',
666                                 'add_args' => $args
667                         ) );
668                         if ( $this->paging_text ) {
669                                 $this->paging_text = sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>%s',
670                                         number_format_i18n( ( $this->page - 1 ) * $this->users_per_page + 1 ),
671                                         number_format_i18n( min( $this->page * $this->users_per_page, $this->total_users_for_query ) ),
672                                         number_format_i18n( $this->total_users_for_query ),
673                                         $this->paging_text
674                                 );
675                         }
676                 }
677         }
678
679         /**
680          * {@internal Missing Short Description}}
681          *
682          * {@internal Missing Long Description}}
683          *
684          * @since unknown
685          * @access public
686          *
687          * @return unknown
688          */
689         function get_results() {
690                 return (array) $this->results;
691         }
692
693         /**
694          * Displaying paging text.
695          *
696          * @see do_paging() Builds paging text.
697          *
698          * @since unknown
699          * @access public
700          */
701         function page_links() {
702                 echo $this->paging_text;
703         }
704
705         /**
706          * Whether paging is enabled.
707          *
708          * @see do_paging() Builds paging text.
709          *
710          * @since unknown
711          * @access public
712          *
713          * @return bool
714          */
715         function results_are_paged() {
716                 if ( $this->paging_text )
717                         return true;
718                 return false;
719         }
720
721         /**
722          * Whether there are search terms.
723          *
724          * @since unknown
725          * @access public
726          *
727          * @return bool
728          */
729         function is_search() {
730                 if ( $this->search_term )
731                         return true;
732                 return false;
733         }
734 }
735 endif;
736
737 ?>