/bp-settings/bp-settings-actions.php

  1. <?php 
  2. /** 
  3. * BuddyPress Settings Actions 
  4. * 
  5. * @todo split actions into separate screen functions 
  6. * @package BuddyPress 
  7. * @subpackage SettingsActions 
  8. * @since 1.5.0 
  9. */ 
  10.  
  11. // Exit if accessed directly. 
  12. defined( 'ABSPATH' ) || exit; 
  13.  
  14. /** 
  15. * Handles the changing and saving of user email addresses and passwords. 
  16. * 
  17. * We do quite a bit of logic and error handling here to make sure that users 
  18. * do not accidentally lock themselves out of their accounts. We also try to 
  19. * provide as accurate of feedback as possible without exposing anyone else's 
  20. * information to them. 
  21. * 
  22. * Special considerations are made for super admins that are able to edit any 
  23. * users accounts already, without knowing their existing password. 
  24. * 
  25. * @since 1.6.0 
  26. * 
  27. * @global BuddyPress $bp 
  28. */ 
  29. function bp_settings_action_general() { 
  30.  
  31. // Bail if not a POST action. 
  32. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  33. return; 
  34.  
  35. // Bail if no submit action. 
  36. if ( ! isset( $_POST['submit'] ) ) 
  37. return; 
  38.  
  39. // Bail if not in settings. 
  40. if ( ! bp_is_settings_component() || ! bp_is_current_action( 'general' ) ) 
  41. return; 
  42.  
  43. // 404 if there are any additional action variables attached 
  44. if ( bp_action_variables() ) { 
  45. bp_do_404(); 
  46. return; 
  47.  
  48. // Define local defaults 
  49. $bp = buddypress(); // The instance 
  50. $email_error = false; // invalid|blocked|taken|empty|nochange 
  51. $pass_error = false; // invalid|mismatch|empty|nochange 
  52. $pass_changed = false; // true if the user changes their password 
  53. $email_changed = false; // true if the user changes their email 
  54. $feedback_type = 'error'; // success|error 
  55. $feedback = array(); // array of strings for feedback. 
  56.  
  57. // Nonce check. 
  58. check_admin_referer('bp_settings_general'); 
  59.  
  60. // Validate the user again for the current password when making a big change. 
  61. if ( ( is_super_admin() ) || ( !empty( $_POST['pwd'] ) && wp_check_password( $_POST['pwd'], $bp->displayed_user->userdata->user_pass, bp_displayed_user_id() ) ) ) { 
  62.  
  63. $update_user = get_userdata( bp_displayed_user_id() ); 
  64.  
  65. /** Email Change Attempt ******************************************/ 
  66.  
  67. if ( !empty( $_POST['email'] ) ) { 
  68.  
  69. // What is missing from the profile page vs signup - 
  70. // let's double check the goodies. 
  71. $user_email = sanitize_email( esc_html( trim( $_POST['email'] ) ) ); 
  72. $old_user_email = $bp->displayed_user->userdata->user_email; 
  73.  
  74. // User is changing email address. 
  75. if ( $old_user_email != $user_email ) { 
  76.  
  77. // Run some tests on the email address. 
  78. $email_checks = bp_core_validate_email_address( $user_email ); 
  79.  
  80. if ( true !== $email_checks ) { 
  81. if ( isset( $email_checks['invalid'] ) ) { 
  82. $email_error = 'invalid'; 
  83.  
  84. if ( isset( $email_checks['domain_banned'] ) || isset( $email_checks['domain_not_allowed'] ) ) { 
  85. $email_error = 'blocked'; 
  86.  
  87. if ( isset( $email_checks['in_use'] ) ) { 
  88. $email_error = 'taken'; 
  89.  
  90. // Store a hash to enable email validation. 
  91. if ( false === $email_error ) { 
  92. $hash = wp_generate_password( 32, false ); 
  93.  
  94. $pending_email = array( 
  95. 'hash' => $hash,  
  96. 'newemail' => $user_email,  
  97. ); 
  98.  
  99. bp_update_user_meta( bp_displayed_user_id(), 'pending_email_change', $pending_email ); 
  100. $verify_link = bp_displayed_user_domain() . bp_get_settings_slug() . '/?verify_email_change=' . $hash; 
  101.  
  102. // Send the verification email. 
  103. $args = array( 
  104. 'tokens' => array( 
  105. 'displayname' => bp_core_get_user_displayname( bp_displayed_user_id() ),  
  106. 'old-user.email' => $old_user_email,  
  107. 'user.email' => $user_email,  
  108. 'verify.url' => esc_url( $verify_link ),  
  109. ),  
  110. ); 
  111. bp_send_email( 'settings-verify-email-change', bp_displayed_user_id(), $args ); 
  112.  
  113. // We mark that the change has taken place so as to ensure a 
  114. // success message, even though verification is still required. 
  115. $_POST['email'] = $update_user->user_email; 
  116. $email_changed = true; 
  117.  
  118. // No change. 
  119. } else { 
  120. $email_error = false; 
  121.  
  122. // Email address cannot be empty. 
  123. } else { 
  124. $email_error = 'empty'; 
  125.  
  126. /** Password Change Attempt ***************************************/ 
  127.  
  128. if ( !empty( $_POST['pass1'] ) && !empty( $_POST['pass2'] ) ) { 
  129.  
  130. if ( ( $_POST['pass1'] == $_POST['pass2'] ) && !strpos( " " . $_POST['pass1'], "\\" ) ) { 
  131.  
  132. // Password change attempt is successful. 
  133. if ( ( ! empty( $_POST['pwd'] ) && $_POST['pwd'] != $_POST['pass1'] ) || is_super_admin() ) { 
  134. $update_user->user_pass = $_POST['pass1']; 
  135. $pass_changed = true; 
  136.  
  137. // The new password is the same as the current password. 
  138. } else { 
  139. $pass_error = 'same'; 
  140.  
  141. // Password change attempt was unsuccessful. 
  142. } else { 
  143. $pass_error = 'mismatch'; 
  144.  
  145. // Both password fields were empty. 
  146. } elseif ( empty( $_POST['pass1'] ) && empty( $_POST['pass2'] ) ) { 
  147. $pass_error = false; 
  148.  
  149. // One of the password boxes was left empty. 
  150. } elseif ( ( empty( $_POST['pass1'] ) && !empty( $_POST['pass2'] ) ) || ( !empty( $_POST['pass1'] ) && empty( $_POST['pass2'] ) ) ) { 
  151. $pass_error = 'empty'; 
  152.  
  153. // The structure of the $update_user object changed in WP 3.3, but 
  154. // wp_update_user() still expects the old format. 
  155. if ( isset( $update_user->data ) && is_object( $update_user->data ) ) { 
  156. $update_user = $update_user->data; 
  157. $update_user = get_object_vars( $update_user ); 
  158.  
  159. // Unset the password field to prevent it from emptying out the 
  160. // user's user_pass field in the database. 
  161. // @see wp_update_user(). 
  162. if ( false === $pass_changed ) { 
  163. unset( $update_user['user_pass'] ); 
  164.  
  165. // Clear cached data, so that the changed settings take effect 
  166. // on the current page load. 
  167. if ( ( false === $email_error ) && ( false === $pass_error ) && ( wp_update_user( $update_user ) ) ) { 
  168. wp_cache_delete( 'bp_core_userdata_' . bp_displayed_user_id(), 'bp' ); 
  169. $bp->displayed_user->userdata = bp_core_get_core_userdata( bp_displayed_user_id() ); 
  170.  
  171. // Password Error. 
  172. } else { 
  173. $pass_error = 'invalid'; 
  174.  
  175. // Email feedback. 
  176. switch ( $email_error ) { 
  177. case 'invalid' : 
  178. $feedback['email_invalid'] = __( 'That email address is invalid. Check the formatting and try again.', 'buddypress' ); 
  179. break; 
  180. case 'blocked' : 
  181. $feedback['email_blocked'] = __( 'That email address is currently unavailable for use.', 'buddypress' ); 
  182. break; 
  183. case 'taken' : 
  184. $feedback['email_taken'] = __( 'That email address is already taken.', 'buddypress' ); 
  185. break; 
  186. case 'empty' : 
  187. $feedback['email_empty'] = __( 'Email address cannot be empty.', 'buddypress' ); 
  188. break; 
  189. case false : 
  190. // No change. 
  191. break; 
  192.  
  193. // Password feedback. 
  194. switch ( $pass_error ) { 
  195. case 'invalid' : 
  196. $feedback['pass_error'] = __( 'Your current password is invalid.', 'buddypress' ); 
  197. break; 
  198. case 'mismatch' : 
  199. $feedback['pass_mismatch'] = __( 'The new password fields did not match.', 'buddypress' ); 
  200. break; 
  201. case 'empty' : 
  202. $feedback['pass_empty'] = __( 'One of the password fields was empty.', 'buddypress' ); 
  203. break; 
  204. case 'same' : 
  205. $feedback['pass_same'] = __( 'The new password must be different from the current password.', 'buddypress' ); 
  206. break; 
  207. case false : 
  208. // No change. 
  209. break; 
  210.  
  211. // No errors so show a simple success message. 
  212. if ( ( ( false === $email_error ) || ( false == $pass_error ) ) && ( ( true === $pass_changed ) || ( true === $email_changed ) ) ) { 
  213. $feedback[] = __( 'Your settings have been saved.', 'buddypress' ); 
  214. $feedback_type = 'success'; 
  215.  
  216. // Some kind of errors occurred. 
  217. } elseif ( ( ( false === $email_error ) || ( false === $pass_error ) ) && ( ( false === $pass_changed ) || ( false === $email_changed ) ) ) { 
  218. if ( bp_is_my_profile() ) { 
  219. $feedback['nochange'] = __( 'No changes were made to your account.', 'buddypress' ); 
  220. } else { 
  221. $feedback['nochange'] = __( 'No changes were made to this account.', 'buddypress' ); 
  222.  
  223. // Set the feedback. 
  224. bp_core_add_message( implode( "\n", $feedback ), $feedback_type ); 
  225.  
  226. /** 
  227. * Fires after the general settings have been saved, and before redirect. 
  228. * 
  229. * @since 1.5.0 
  230. */ 
  231. do_action( 'bp_core_general_settings_after_save' ); 
  232.  
  233. // Redirect to prevent issues with browser back button. 
  234. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . bp_get_settings_slug() . '/general' ) ); 
  235. add_action( 'bp_actions', 'bp_settings_action_general' ); 
  236.  
  237. /** 
  238. * Handles the changing and saving of user notification settings. 
  239. * 
  240. * @since 1.6.0 
  241. */ 
  242. function bp_settings_action_notifications() { 
  243.  
  244. // Bail if not a POST action. 
  245. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  246. return; 
  247.  
  248. // Bail if no submit action. 
  249. if ( ! isset( $_POST['submit'] ) ) 
  250. return; 
  251.  
  252. // Bail if not in settings. 
  253. if ( ! bp_is_settings_component() || ! bp_is_current_action( 'notifications' ) ) 
  254. return false; 
  255.  
  256. // 404 if there are any additional action variables attached 
  257. if ( bp_action_variables() ) { 
  258. bp_do_404(); 
  259. return; 
  260.  
  261. check_admin_referer( 'bp_settings_notifications' ); 
  262.  
  263. bp_settings_update_notification_settings( bp_displayed_user_id(), (array) $_POST['notifications'] ); 
  264.  
  265. // Switch feedback for super admins. 
  266. if ( bp_is_my_profile() ) { 
  267. bp_core_add_message( __( 'Your notification settings have been saved.', 'buddypress' ), 'success' ); 
  268. } else { 
  269. bp_core_add_message( __( "This user's notification settings have been saved.", 'buddypress' ), 'success' ); 
  270.  
  271. /** 
  272. * Fires after the notification settings have been saved, and before redirect. 
  273. * 
  274. * @since 1.5.0 
  275. */ 
  276. do_action( 'bp_core_notification_settings_after_save' ); 
  277.  
  278. bp_core_redirect( bp_displayed_user_domain() . bp_get_settings_slug() . '/notifications/' ); 
  279. add_action( 'bp_actions', 'bp_settings_action_notifications' ); 
  280.  
  281. /** 
  282. * Handles the setting of user capabilities, spamming, hamming, role, etc... 
  283. * 
  284. * @since 1.6.0 
  285. */ 
  286. function bp_settings_action_capabilities() { 
  287.  
  288. // Bail if not a POST action. 
  289. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  290. return; 
  291.  
  292. // Bail if no submit action. 
  293. if ( ! isset( $_POST['capabilities-submit'] ) ) 
  294. return; 
  295.  
  296. // Bail if not in settings. 
  297. if ( ! bp_is_settings_component() || ! bp_is_current_action( 'capabilities' ) ) 
  298. return false; 
  299.  
  300. // 404 if there are any additional action variables attached 
  301. if ( bp_action_variables() ) { 
  302. bp_do_404(); 
  303. return; 
  304.  
  305. // Only super admins can currently spam users (but they can't spam 
  306. // themselves). 
  307. if ( ! is_super_admin() || bp_is_my_profile() ) { 
  308. return; 
  309.  
  310. // Nonce check. 
  311. check_admin_referer( 'capabilities' ); 
  312.  
  313. /** 
  314. * Fires before the capabilities settings have been saved. 
  315. * 
  316. * @since 1.6.0 
  317. */ 
  318. do_action( 'bp_settings_capabilities_before_save' ); 
  319.  
  320. /** Spam **************************************************************/ 
  321.  
  322. $is_spammer = !empty( $_POST['user-spammer'] ) ? true : false; 
  323.  
  324. if ( bp_is_user_spammer( bp_displayed_user_id() ) != $is_spammer ) { 
  325. $status = ( true == $is_spammer ) ? 'spam' : 'ham'; 
  326. bp_core_process_spammer_status( bp_displayed_user_id(), $status ); 
  327.  
  328. /** 
  329. * Fires after processing a user as a spammer. 
  330. * 
  331. * @since 1.1.0 
  332. * 
  333. * @param int $value ID of the currently displayed user. 
  334. * @param string $status Determined status of "spam" or "ham" for the displayed user. 
  335. */ 
  336. do_action( 'bp_core_action_set_spammer_status', bp_displayed_user_id(), $status ); 
  337.  
  338. /** Other *************************************************************/ 
  339.  
  340. /** 
  341. * Fires after the capabilities settings have been saved and before redirect. 
  342. * 
  343. * @since 1.6.0 
  344. */ 
  345. do_action( 'bp_settings_capabilities_after_save' ); 
  346.  
  347. // Redirect to the root domain. 
  348. bp_core_redirect( bp_displayed_user_domain() . bp_get_settings_slug() . '/capabilities/' ); 
  349. add_action( 'bp_actions', 'bp_settings_action_capabilities' ); 
  350.  
  351. /** 
  352. * Handles the deleting of a user. 
  353. * 
  354. * @since 1.6.0 
  355. */ 
  356. function bp_settings_action_delete_account() { 
  357.  
  358. // Bail if not a POST action. 
  359. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) 
  360. return; 
  361.  
  362. // Bail if no submit action. 
  363. if ( ! isset( $_POST['delete-account-understand'] ) ) 
  364. return; 
  365.  
  366. // Bail if not in settings. 
  367. if ( ! bp_is_settings_component() || ! bp_is_current_action( 'delete-account' ) ) 
  368. return false; 
  369.  
  370. // 404 if there are any additional action variables attached 
  371. if ( bp_action_variables() ) { 
  372. bp_do_404(); 
  373. return; 
  374.  
  375. // Bail if account deletion is disabled. 
  376. if ( bp_disable_account_deletion() && ! bp_current_user_can( 'delete_users' ) ) { 
  377. return false; 
  378.  
  379. // Nonce check. 
  380. check_admin_referer( 'delete-account' ); 
  381.  
  382. // Get username now because it might be gone soon! 
  383. $username = bp_get_displayed_user_fullname(); 
  384.  
  385. // Delete the users account. 
  386. if ( bp_core_delete_account( bp_displayed_user_id() ) ) { 
  387.  
  388. // Add feedback after deleting a user. 
  389. bp_core_add_message( sprintf( __( '%s was successfully deleted.', 'buddypress' ), $username ), 'success' ); 
  390.  
  391. // Redirect to the root domain. 
  392. bp_core_redirect( bp_get_root_domain() ); 
  393. add_action( 'bp_actions', 'bp_settings_action_delete_account' ); 
  394.  
  395. /** 
  396. * Process email change verification or cancel requests. 
  397. * 
  398. * @since 2.1.0 
  399. */ 
  400. function bp_settings_verify_email_change() { 
  401. if ( ! bp_is_settings_component() ) { 
  402. return; 
  403.  
  404. if ( ! bp_is_my_profile() ) { 
  405. return; 
  406.  
  407. $redirect_to = trailingslashit( bp_displayed_user_domain() . bp_get_settings_slug() ); 
  408.  
  409. // Email change is being verified. 
  410. if ( isset( $_GET['verify_email_change'] ) ) { 
  411. $pending_email = bp_get_user_meta( bp_displayed_user_id(), 'pending_email_change', true ); 
  412.  
  413. // Bail if the hash provided doesn't match the one saved in the database. 
  414. if ( ! hash_equals( urldecode( $_GET['verify_email_change'] ), $pending_email['hash'] ) ) { 
  415. return; 
  416.  
  417. $email_changed = wp_update_user( array( 
  418. 'ID' => bp_displayed_user_id(),  
  419. 'user_email' => trim( $pending_email['newemail'] ),  
  420. ) ); 
  421.  
  422. if ( $email_changed ) { 
  423. // Delete object cache for displayed user. 
  424. wp_cache_delete( 'bp_core_userdata_' . bp_displayed_user_id(), 'bp' ); 
  425.  
  426. // Delete the pending email change key. 
  427. bp_delete_user_meta( bp_displayed_user_id(), 'pending_email_change' ); 
  428.  
  429. // Post a success message and redirect. 
  430. bp_core_add_message( __( 'You have successfully verified your new email address.', 'buddypress' ) ); 
  431. } else { 
  432. // Unknown error. 
  433. bp_core_add_message( __( 'There was a problem verifying your new email address. Please try again.', 'buddypress' ), 'error' ); 
  434.  
  435. bp_core_redirect( $redirect_to ); 
  436. die(); 
  437.  
  438. // Email change is being dismissed. 
  439. } elseif ( ! empty( $_GET['dismiss_email_change'] ) ) { 
  440. $nonce_check = isset( $_GET['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'bp_dismiss_email_change' ); 
  441.  
  442. if ( $nonce_check ) { 
  443. bp_delete_user_meta( bp_displayed_user_id(), 'pending_email_change' ); 
  444. bp_core_add_message( __( 'You have successfully dismissed your pending email change.', 'buddypress' ) ); 
  445.  
  446. bp_core_redirect( $redirect_to ); 
  447. die(); 
  448. add_action( 'bp_actions', 'bp_settings_verify_email_change' ); 
  449.  
  450. /** 
  451. * Removes 'Email' sub nav, if no component has registered options there. 
  452. * 
  453. * @since 2.2.0 
  454. */ 
  455. function bp_settings_remove_email_subnav() { 
  456. if ( ! has_action( 'bp_notification_settings' ) ) { 
  457. bp_core_remove_subnav_item( BP_SETTINGS_SLUG, 'notifications' ); 
  458. add_action( 'bp_actions', 'bp_settings_remove_email_subnav' ); 
.