user.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. <?php
  2. /**
  3. * WordPress user administration API.
  4. *
  5. * @package WordPress
  6. * @subpackage Administration
  7. */
  8. /**
  9. * Creates a new user from the "Users" form using $_POST information.
  10. *
  11. * @since 2.0.0
  12. *
  13. * @return int|WP_Error WP_Error or User ID.
  14. */
  15. function add_user() {
  16. return edit_user();
  17. }
  18. /**
  19. * Edit user settings based on contents of $_POST
  20. *
  21. * Used on user-edit.php and profile.php to manage and process user options, passwords etc.
  22. *
  23. * @since 2.0.0
  24. *
  25. * @param int $user_id Optional. User ID.
  26. * @return int|WP_Error user id of the updated user.
  27. */
  28. function edit_user( $user_id = 0 ) {
  29. $wp_roles = wp_roles();
  30. $user = new stdClass;
  31. $user_id = (int) $user_id;
  32. if ( $user_id ) {
  33. $update = true;
  34. $user->ID = $user_id;
  35. $userdata = get_userdata( $user_id );
  36. $user->user_login = wp_slash( $userdata->user_login );
  37. } else {
  38. $update = false;
  39. }
  40. if ( ! $update && isset( $_POST['user_login'] ) ) {
  41. $user->user_login = sanitize_user( $_POST['user_login'], true );
  42. }
  43. $pass1 = '';
  44. $pass2 = '';
  45. if ( isset( $_POST['pass1'] ) ) {
  46. $pass1 = $_POST['pass1'];
  47. }
  48. if ( isset( $_POST['pass2'] ) ) {
  49. $pass2 = $_POST['pass2'];
  50. }
  51. if ( isset( $_POST['role'] ) && current_user_can( 'promote_users' ) && ( ! $user_id || current_user_can( 'promote_user', $user_id ) ) ) {
  52. $new_role = sanitize_text_field( $_POST['role'] );
  53. // If the new role isn't editable by the logged-in user die with error.
  54. $editable_roles = get_editable_roles();
  55. if ( ! empty( $new_role ) && empty( $editable_roles[ $new_role ] ) ) {
  56. wp_die( __( 'Sorry, you are not allowed to give users that role.' ), 403 );
  57. }
  58. $potential_role = isset( $wp_roles->role_objects[ $new_role ] ) ? $wp_roles->role_objects[ $new_role ] : false;
  59. /*
  60. * Don't let anyone with 'promote_users' edit their own role to something without it.
  61. * Multisite super admins can freely edit their roles, they possess all caps.
  62. */
  63. if (
  64. ( is_multisite() && current_user_can( 'manage_network_users' ) ) ||
  65. $user_id !== get_current_user_id() ||
  66. ( $potential_role && $potential_role->has_cap( 'promote_users' ) )
  67. ) {
  68. $user->role = $new_role;
  69. }
  70. }
  71. if ( isset( $_POST['email'] ) ) {
  72. $user->user_email = sanitize_text_field( wp_unslash( $_POST['email'] ) );
  73. }
  74. if ( isset( $_POST['url'] ) ) {
  75. if ( empty( $_POST['url'] ) || $_POST['url'] == 'http://' ) {
  76. $user->user_url = '';
  77. } else {
  78. $user->user_url = esc_url_raw( $_POST['url'] );
  79. $protocols = implode( '|', array_map( 'preg_quote', wp_allowed_protocols() ) );
  80. $user->user_url = preg_match( '/^(' . $protocols . '):/is', $user->user_url ) ? $user->user_url : 'http://' . $user->user_url;
  81. }
  82. }
  83. if ( isset( $_POST['first_name'] ) ) {
  84. $user->first_name = sanitize_text_field( $_POST['first_name'] );
  85. }
  86. if ( isset( $_POST['last_name'] ) ) {
  87. $user->last_name = sanitize_text_field( $_POST['last_name'] );
  88. }
  89. if ( isset( $_POST['nickname'] ) ) {
  90. $user->nickname = sanitize_text_field( $_POST['nickname'] );
  91. }
  92. if ( isset( $_POST['display_name'] ) ) {
  93. $user->display_name = sanitize_text_field( $_POST['display_name'] );
  94. }
  95. if ( isset( $_POST['description'] ) ) {
  96. $user->description = trim( $_POST['description'] );
  97. }
  98. foreach ( wp_get_user_contact_methods( $user ) as $method => $name ) {
  99. if ( isset( $_POST[ $method ] ) ) {
  100. $user->$method = sanitize_text_field( $_POST[ $method ] );
  101. }
  102. }
  103. if ( $update ) {
  104. $user->rich_editing = isset( $_POST['rich_editing'] ) && 'false' === $_POST['rich_editing'] ? 'false' : 'true';
  105. $user->syntax_highlighting = isset( $_POST['syntax_highlighting'] ) && 'false' === $_POST['syntax_highlighting'] ? 'false' : 'true';
  106. $user->admin_color = isset( $_POST['admin_color'] ) ? sanitize_text_field( $_POST['admin_color'] ) : 'fresh';
  107. $user->show_admin_bar_front = isset( $_POST['admin_bar_front'] ) ? 'true' : 'false';
  108. $user->locale = '';
  109. if ( isset( $_POST['locale'] ) ) {
  110. $locale = sanitize_text_field( $_POST['locale'] );
  111. if ( 'site-default' === $locale ) {
  112. $locale = '';
  113. } elseif ( '' === $locale ) {
  114. $locale = 'en_US';
  115. } elseif ( ! in_array( $locale, get_available_languages(), true ) ) {
  116. $locale = '';
  117. }
  118. $user->locale = $locale;
  119. }
  120. }
  121. $user->comment_shortcuts = isset( $_POST['comment_shortcuts'] ) && 'true' == $_POST['comment_shortcuts'] ? 'true' : '';
  122. $user->use_ssl = 0;
  123. if ( ! empty( $_POST['use_ssl'] ) ) {
  124. $user->use_ssl = 1;
  125. }
  126. $errors = new WP_Error();
  127. /* checking that username has been typed */
  128. if ( $user->user_login == '' ) {
  129. $errors->add( 'user_login', __( '<strong>ERROR</strong>: Please enter a username.' ) );
  130. }
  131. /* checking that nickname has been typed */
  132. if ( $update && empty( $user->nickname ) ) {
  133. $errors->add( 'nickname', __( '<strong>ERROR</strong>: Please enter a nickname.' ) );
  134. }
  135. /**
  136. * Fires before the password and confirm password fields are checked for congruity.
  137. *
  138. * @since 1.5.1
  139. *
  140. * @param string $user_login The username.
  141. * @param string $pass1 The password (passed by reference).
  142. * @param string $pass2 The confirmed password (passed by reference).
  143. */
  144. do_action_ref_array( 'check_passwords', array( $user->user_login, &$pass1, &$pass2 ) );
  145. // Check for blank password when adding a user.
  146. if ( ! $update && empty( $pass1 ) ) {
  147. $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter a password.' ), array( 'form-field' => 'pass1' ) );
  148. }
  149. // Check for "\" in password.
  150. if ( false !== strpos( wp_unslash( $pass1 ), '\\' ) ) {
  151. $errors->add( 'pass', __( '<strong>ERROR</strong>: Passwords may not contain the character "\\".' ), array( 'form-field' => 'pass1' ) );
  152. }
  153. // Checking the password has been typed twice the same.
  154. if ( ( $update || ! empty( $pass1 ) ) && $pass1 != $pass2 ) {
  155. $errors->add( 'pass', __( '<strong>ERROR</strong>: Please enter the same password in both password fields.' ), array( 'form-field' => 'pass1' ) );
  156. }
  157. if ( ! empty( $pass1 ) ) {
  158. $user->user_pass = $pass1;
  159. }
  160. if ( ! $update && isset( $_POST['user_login'] ) && ! validate_username( $_POST['user_login'] ) ) {
  161. $errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is invalid because it uses illegal characters. Please enter a valid username.' ) );
  162. }
  163. if ( ! $update && username_exists( $user->user_login ) ) {
  164. $errors->add( 'user_login', __( '<strong>ERROR</strong>: This username is already registered. Please choose another one.' ) );
  165. }
  166. /** This filter is documented in wp-includes/user.php */
  167. $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() );
  168. if ( in_array( strtolower( $user->user_login ), array_map( 'strtolower', $illegal_logins ) ) ) {
  169. $errors->add( 'invalid_username', __( '<strong>ERROR</strong>: Sorry, that username is not allowed.' ) );
  170. }
  171. /* checking email address */
  172. if ( empty( $user->user_email ) ) {
  173. $errors->add( 'empty_email', __( '<strong>ERROR</strong>: Please enter an email address.' ), array( 'form-field' => 'email' ) );
  174. } elseif ( ! is_email( $user->user_email ) ) {
  175. $errors->add( 'invalid_email', __( '<strong>ERROR</strong>: The email address isn&#8217;t correct.' ), array( 'form-field' => 'email' ) );
  176. } else {
  177. $owner_id = email_exists( $user->user_email );
  178. if ( $owner_id && ( ! $update || ( $owner_id != $user->ID ) ) ) {
  179. $errors->add( 'email_exists', __( '<strong>ERROR</strong>: This email is already registered, please choose another one.' ), array( 'form-field' => 'email' ) );
  180. }
  181. }
  182. /**
  183. * Fires before user profile update errors are returned.
  184. *
  185. * @since 2.8.0
  186. *
  187. * @param WP_Error $errors WP_Error object (passed by reference).
  188. * @param bool $update Whether this is a user update.
  189. * @param stdClass $user User object (passed by reference).
  190. */
  191. do_action_ref_array( 'user_profile_update_errors', array( &$errors, $update, &$user ) );
  192. if ( $errors->has_errors() ) {
  193. return $errors;
  194. }
  195. if ( $update ) {
  196. $user_id = wp_update_user( $user );
  197. } else {
  198. $user_id = wp_insert_user( $user );
  199. $notify = isset( $_POST['send_user_notification'] ) ? 'both' : 'admin';
  200. /**
  201. * Fires after a new user has been created.
  202. *
  203. * @since 4.4.0
  204. *
  205. * @param int $user_id ID of the newly created user.
  206. * @param string $notify Type of notification that should happen. See wp_send_new_user_notifications()
  207. * for more information on possible values.
  208. */
  209. do_action( 'edit_user_created_user', $user_id, $notify );
  210. }
  211. return $user_id;
  212. }
  213. /**
  214. * Fetch a filtered list of user roles that the current user is
  215. * allowed to edit.
  216. *
  217. * Simple function whose main purpose is to allow filtering of the
  218. * list of roles in the $wp_roles object so that plugins can remove
  219. * inappropriate ones depending on the situation or user making edits.
  220. * Specifically because without filtering anyone with the edit_users
  221. * capability can edit others to be administrators, even if they are
  222. * only editors or authors. This filter allows admins to delegate
  223. * user management.
  224. *
  225. * @since 2.8.0
  226. *
  227. * @return array[] Array of arrays containing role information.
  228. */
  229. function get_editable_roles() {
  230. $all_roles = wp_roles()->roles;
  231. /**
  232. * Filters the list of editable roles.
  233. *
  234. * @since 2.8.0
  235. *
  236. * @param array[] $all_roles Array of arrays containing role information.
  237. */
  238. $editable_roles = apply_filters( 'editable_roles', $all_roles );
  239. return $editable_roles;
  240. }
  241. /**
  242. * Retrieve user data and filter it.
  243. *
  244. * @since 2.0.5
  245. *
  246. * @param int $user_id User ID.
  247. * @return WP_User|bool WP_User object on success, false on failure.
  248. */
  249. function get_user_to_edit( $user_id ) {
  250. $user = get_userdata( $user_id );
  251. if ( $user ) {
  252. $user->filter = 'edit';
  253. }
  254. return $user;
  255. }
  256. /**
  257. * Retrieve the user's drafts.
  258. *
  259. * @since 2.0.0
  260. *
  261. * @global wpdb $wpdb WordPress database abstraction object.
  262. *
  263. * @param int $user_id User ID.
  264. * @return array
  265. */
  266. function get_users_drafts( $user_id ) {
  267. global $wpdb;
  268. $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 );
  269. /**
  270. * Filters the user's drafts query string.
  271. *
  272. * @since 2.0.0
  273. *
  274. * @param string $query The user's drafts query string.
  275. */
  276. $query = apply_filters( 'get_users_drafts', $query );
  277. return $wpdb->get_results( $query );
  278. }
  279. /**
  280. * Remove user and optionally reassign posts and links to another user.
  281. *
  282. * If the $reassign parameter is not assigned to a User ID, then all posts will
  283. * be deleted of that user. The action {@see 'delete_user'} that is passed the User ID
  284. * being deleted will be run after the posts are either reassigned or deleted.
  285. * The user meta will also be deleted that are for that User ID.
  286. *
  287. * @since 2.0.0
  288. *
  289. * @global wpdb $wpdb WordPress database abstraction object.
  290. *
  291. * @param int $id User ID.
  292. * @param int $reassign Optional. Reassign posts and links to new User ID.
  293. * @return bool True when finished.
  294. */
  295. function wp_delete_user( $id, $reassign = null ) {
  296. global $wpdb;
  297. if ( ! is_numeric( $id ) ) {
  298. return false;
  299. }
  300. $id = (int) $id;
  301. $user = new WP_User( $id );
  302. if ( ! $user->exists() ) {
  303. return false;
  304. }
  305. // Normalize $reassign to null or a user ID. 'novalue' was an older default.
  306. if ( 'novalue' === $reassign ) {
  307. $reassign = null;
  308. } elseif ( null !== $reassign ) {
  309. $reassign = (int) $reassign;
  310. }
  311. /**
  312. * Fires immediately before a user is deleted from the database.
  313. *
  314. * @since 2.0.0
  315. *
  316. * @param int $id ID of the user to delete.
  317. * @param int|null $reassign ID of the user to reassign posts and links to.
  318. * Default null, for no reassignment.
  319. */
  320. do_action( 'delete_user', $id, $reassign );
  321. if ( null === $reassign ) {
  322. $post_types_to_delete = array();
  323. foreach ( get_post_types( array(), 'objects' ) as $post_type ) {
  324. if ( $post_type->delete_with_user ) {
  325. $post_types_to_delete[] = $post_type->name;
  326. } elseif ( null === $post_type->delete_with_user && post_type_supports( $post_type->name, 'author' ) ) {
  327. $post_types_to_delete[] = $post_type->name;
  328. }
  329. }
  330. /**
  331. * Filters the list of post types to delete with a user.
  332. *
  333. * @since 3.4.0
  334. *
  335. * @param string[] $post_types_to_delete Array of post types to delete.
  336. * @param int $id User ID.
  337. */
  338. $post_types_to_delete = apply_filters( 'post_types_to_delete_with_user', $post_types_to_delete, $id );
  339. $post_types_to_delete = implode( "', '", $post_types_to_delete );
  340. $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d AND post_type IN ('$post_types_to_delete')", $id ) );
  341. if ( $post_ids ) {
  342. foreach ( $post_ids as $post_id ) {
  343. wp_delete_post( $post_id );
  344. }
  345. }
  346. // Clean links
  347. $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
  348. if ( $link_ids ) {
  349. foreach ( $link_ids as $link_id ) {
  350. wp_delete_link( $link_id );
  351. }
  352. }
  353. } else {
  354. $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $id ) );
  355. $wpdb->update( $wpdb->posts, array( 'post_author' => $reassign ), array( 'post_author' => $id ) );
  356. if ( ! empty( $post_ids ) ) {
  357. foreach ( $post_ids as $post_id ) {
  358. clean_post_cache( $post_id );
  359. }
  360. }
  361. $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $id ) );
  362. $wpdb->update( $wpdb->links, array( 'link_owner' => $reassign ), array( 'link_owner' => $id ) );
  363. if ( ! empty( $link_ids ) ) {
  364. foreach ( $link_ids as $link_id ) {
  365. clean_bookmark_cache( $link_id );
  366. }
  367. }
  368. }
  369. // FINALLY, delete user
  370. if ( is_multisite() ) {
  371. remove_user_from_blog( $id, get_current_blog_id() );
  372. } else {
  373. $meta = $wpdb->get_col( $wpdb->prepare( "SELECT umeta_id FROM $wpdb->usermeta WHERE user_id = %d", $id ) );
  374. foreach ( $meta as $mid ) {
  375. delete_metadata_by_mid( 'user', $mid );
  376. }
  377. $wpdb->delete( $wpdb->users, array( 'ID' => $id ) );
  378. }
  379. clean_user_cache( $user );
  380. /**
  381. * Fires immediately after a user is deleted from the database.
  382. *
  383. * @since 2.9.0
  384. *
  385. * @param int $id ID of the deleted user.
  386. * @param int|null $reassign ID of the user to reassign posts and links to.
  387. * Default null, for no reassignment.
  388. */
  389. do_action( 'deleted_user', $id, $reassign );
  390. return true;
  391. }
  392. /**
  393. * Remove all capabilities from user.
  394. *
  395. * @since 2.1.0
  396. *
  397. * @param int $id User ID.
  398. */
  399. function wp_revoke_user( $id ) {
  400. $id = (int) $id;
  401. $user = new WP_User( $id );
  402. $user->remove_all_caps();
  403. }
  404. /**
  405. * @since 2.8.0
  406. *
  407. * @global int $user_ID
  408. *
  409. * @param false $errors Deprecated.
  410. */
  411. function default_password_nag_handler( $errors = false ) {
  412. global $user_ID;
  413. // Short-circuit it.
  414. if ( ! get_user_option( 'default_password_nag' ) ) {
  415. return;
  416. }
  417. // get_user_setting = JS saved UI setting. else no-js-fallback code.
  418. if ( 'hide' == get_user_setting( 'default_password_nag' ) || isset( $_GET['default_password_nag'] ) && '0' == $_GET['default_password_nag'] ) {
  419. delete_user_setting( 'default_password_nag' );
  420. update_user_option( $user_ID, 'default_password_nag', false, true );
  421. }
  422. }
  423. /**
  424. * @since 2.8.0
  425. *
  426. * @param int $user_ID
  427. * @param object $old_data
  428. */
  429. function default_password_nag_edit_user( $user_ID, $old_data ) {
  430. // Short-circuit it.
  431. if ( ! get_user_option( 'default_password_nag', $user_ID ) ) {
  432. return;
  433. }
  434. $new_data = get_userdata( $user_ID );
  435. // Remove the nag if the password has been changed.
  436. if ( $new_data->user_pass != $old_data->user_pass ) {
  437. delete_user_setting( 'default_password_nag' );
  438. update_user_option( $user_ID, 'default_password_nag', false, true );
  439. }
  440. }
  441. /**
  442. * @since 2.8.0
  443. *
  444. * @global string $pagenow
  445. */
  446. function default_password_nag() {
  447. global $pagenow;
  448. // Short-circuit it.
  449. if ( 'profile.php' == $pagenow || ! get_user_option( 'default_password_nag' ) ) {
  450. return;
  451. }
  452. echo '<div class="error default-password-nag">';
  453. echo '<p>';
  454. echo '<strong>' . __( 'Notice:' ) . '</strong> ';
  455. _e( 'You&rsquo;re using the auto-generated password for your account. Would you like to change it?' );
  456. echo '</p><p>';
  457. printf( '<a href="%s">' . __( 'Yes, take me to my profile page' ) . '</a> | ', get_edit_profile_url() . '#password' );
  458. printf( '<a href="%s" id="default-password-nag-no">' . __( 'No thanks, do not remind me again' ) . '</a>', '?default_password_nag=0' );
  459. echo '</p></div>';
  460. }
  461. /**
  462. * @since 3.5.0
  463. * @access private
  464. */
  465. function delete_users_add_js() {
  466. ?>
  467. <script>
  468. jQuery(document).ready( function($) {
  469. var submit = $('#submit').prop('disabled', true);
  470. $('input[name="delete_option"]').one('change', function() {
  471. submit.prop('disabled', false);
  472. });
  473. $('#reassign_user').focus( function() {
  474. $('#delete_option1').prop('checked', true).trigger('change');
  475. });
  476. });
  477. </script>
  478. <?php
  479. }
  480. /**
  481. * Optional SSL preference that can be turned on by hooking to the 'personal_options' action.
  482. *
  483. * See the {@see 'personal_options'} action.
  484. *
  485. * @since 2.7.0
  486. *
  487. * @param object $user User data object.
  488. */
  489. function use_ssl_preference( $user ) {
  490. ?>
  491. <tr class="user-use-ssl-wrap">
  492. <th scope="row"><?php _e( 'Use https' ); ?></th>
  493. <td><label for="use_ssl"><input name="use_ssl" type="checkbox" id="use_ssl" value="1" <?php checked( '1', $user->use_ssl ); ?> /> <?php _e( 'Always use https when visiting the admin' ); ?></label></td>
  494. </tr>
  495. <?php
  496. }
  497. /**
  498. * @since MU (3.0.0)
  499. *
  500. * @param string $text
  501. * @return string
  502. */
  503. function admin_created_user_email( $text ) {
  504. $roles = get_editable_roles();
  505. $role = $roles[ $_REQUEST['role'] ];
  506. return sprintf(
  507. /* translators: 1: Site title, 2: Site URL, 3: User role. */
  508. __(
  509. 'Hi,
  510. You\'ve been invited to join \'%1$s\' at
  511. %2$s with the role of %3$s.
  512. If you do not want to join this site please ignore
  513. this email. This invitation will expire in a few days.
  514. Please click the following link to activate your user account:
  515. %%s'
  516. ),
  517. wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ),
  518. home_url(),
  519. wp_specialchars_decode( translate_user_role( $role['name'] ) )
  520. );
  521. }