@@ -226,14 +226,6 @@ function edit_user( $user_id = 0 ) {
226226 do_action_ref_array ( 'user_profile_update_errors ' , array ( &$ errors , $ update , &$ user ) );
227227
228228 if ( $ errors ->has_errors () ) {
229- if ( $ update ) {
230- $ updated_user_id = _edit_user_partial_update ( $ user , $ errors );
231-
232- if ( is_wp_error ( $ updated_user_id ) ) {
233- $ errors ->merge_from ( $ updated_user_id );
234- }
235- }
236-
237229 return $ errors ;
238230 }
239231
@@ -257,77 +249,17 @@ function edit_user( $user_id = 0 ) {
257249 return $ user_id ;
258250}
259251
260- /**
261- * Updates a user with the valid data from a failed profile submission.
262- *
263- * When an existing user update fails due to field-specific validation errors,
264- * the remaining valid fields can still be saved so they are not lost on the
265- * subsequent page load.
266- *
267- * @since 7.1.0
268- * @access private
269- *
270- * @param stdClass $user User data prepared for `wp_update_user()`.
271- * @param WP_Error $errors Validation errors from `edit_user()`.
272- * @return int|WP_Error User ID on success, WP_Error on failure, or 0 if no partial update was attempted.
273- */
274- function _edit_user_partial_update ( $ user , $ errors ) {
275- $ error_fields = _get_edit_user_error_fields ( $ errors );
276-
277- if ( ! $ error_fields ) {
278- return 0 ;
279- }
280-
281- foreach ( $ error_fields as $ field ) {
282- $ property = _get_edit_user_property ( $ field );
283-
284- if ( property_exists ( $ user , $ property ) ) {
285- unset( $ user ->$ property );
286- }
287- }
288-
289- if ( 1 === count ( get_object_vars ( $ user ) ) ) {
290- return 0 ;
291- }
292-
293- return wp_update_user ( $ user );
294- }
295-
296- /**
297- * Maps edit-user form fields to the properties stored by `wp_update_user()`.
298- *
299- * @since 7.1.0
300- * @access private
301- *
302- * @param string $field Form field name.
303- * @return string User property name.
304- */
305- function _get_edit_user_property ( $ field ) {
306- switch ( $ field ) {
307- case 'email ' :
308- return 'user_email ' ;
309- case 'url ' :
310- return 'user_url ' ;
311- case 'pass1 ' :
312- case 'pass2 ' :
313- return 'user_pass ' ;
314- default :
315- return $ field ;
316- }
317- }
318-
319252/**
320253 * Gets the form fields responsible for a failed user update.
321254 *
322- * Only errors that can be mapped back to a specific submitted field are
323- * considered safe for partial saving. Any unknown error aborts the partial
324- * update so the submission remains fully blocked.
255+ * These fields are excluded when rebuilding the edit form from submitted data
256+ * after a failed update.
325257 *
326258 * @since 7.1.0
327259 * @access private
328260 *
329261 * @param WP_Error $errors Validation errors from `edit_user()`.
330- * @return string[] Array of field names that should be excluded from the save .
262+ * @return string[] Array of field names that should not be repopulated .
331263 */
332264function _get_edit_user_error_fields ( $ errors ) {
333265 $ error_fields = array ();
@@ -365,6 +297,119 @@ function _get_edit_user_error_fields( $errors ) {
365297 return array_keys ( $ error_fields );
366298}
367299
300+ /**
301+ * Retrieves user data for the edit screen and overlays safe submitted values.
302+ *
303+ * When an existing user update fails validation, the edit and profile screens
304+ * should preserve submitted values without writing them to the database. Fields
305+ * that produced errors are left at their stored values, and password fields are
306+ * never repopulated.
307+ *
308+ * @since 7.1.0
309+ * @access private
310+ *
311+ * @param int $user_id User ID.
312+ * @param WP_Error $errors Validation errors from `edit_user()`.
313+ * @return WP_User|false WP_User object on success, false on failure.
314+ */
315+ function _get_user_to_edit_from_post ( $ user_id , $ errors ) {
316+ $ user = get_user_to_edit ( $ user_id );
317+ $ is_profile_page = defined ( 'IS_PROFILE_PAGE ' ) && IS_PROFILE_PAGE ;
318+
319+ if ( ! $ user || ! is_wp_error ( $ errors ) || ! $ errors ->has_errors () ) {
320+ return $ user ;
321+ }
322+
323+ $ error_fields = array_flip ( _get_edit_user_error_fields ( $ errors ) );
324+ $ properties = array (
325+ 'first_name ' => 'first_name ' ,
326+ 'last_name ' => 'last_name ' ,
327+ 'nickname ' => 'nickname ' ,
328+ 'display_name ' => 'display_name ' ,
329+ 'email ' => 'user_email ' ,
330+ 'url ' => 'user_url ' ,
331+ 'description ' => 'description ' ,
332+ 'locale ' => 'locale ' ,
333+ 'admin_color ' => 'admin_color ' ,
334+ );
335+
336+ foreach ( $ properties as $ field => $ property ) {
337+ if ( isset ( $ error_fields [ $ field ] ) || ! isset ( $ _POST [ $ field ] ) ) {
338+ continue ;
339+ }
340+
341+ $ user ->$ property = wp_unslash ( $ _POST [ $ field ] );
342+ }
343+
344+ foreach ( wp_get_user_contact_methods ( $ user ) as $ method => $ label ) {
345+ if ( isset ( $ error_fields [ $ method ] ) || ! isset ( $ _POST [ $ method ] ) ) {
346+ continue ;
347+ }
348+
349+ $ user ->$ method = wp_unslash ( $ _POST [ $ method ] );
350+ }
351+
352+ if ( ! isset ( $ error_fields ['rich_editing ' ] ) ) {
353+ $ user ->rich_editing = isset ( $ _POST ['rich_editing ' ] ) && 'false ' === $ _POST ['rich_editing ' ] ? 'false ' : 'true ' ;
354+ }
355+
356+ if ( ! isset ( $ error_fields ['syntax_highlighting ' ] ) ) {
357+ $ user ->syntax_highlighting = isset ( $ _POST ['syntax_highlighting ' ] ) && 'false ' === $ _POST ['syntax_highlighting ' ] ? 'false ' : 'true ' ;
358+ }
359+
360+ if ( ! isset ( $ error_fields ['comment_shortcuts ' ] ) ) {
361+ $ user ->comment_shortcuts = isset ( $ _POST ['comment_shortcuts ' ] ) && 'true ' === $ _POST ['comment_shortcuts ' ] ? 'true ' : '' ;
362+ }
363+
364+ if ( ! isset ( $ error_fields ['admin_bar_front ' ] ) ) {
365+ $ user ->show_admin_bar_front = isset ( $ _POST ['admin_bar_front ' ] ) ? 'true ' : 'false ' ;
366+ }
367+
368+ if ( ! isset ( $ error_fields ['use_ssl ' ] ) ) {
369+ $ user ->use_ssl = ! empty ( $ _POST ['use_ssl ' ] ) ? 1 : 0 ;
370+ }
371+
372+ if ( ! isset ( $ error_fields ['role ' ] )
373+ && ! $ is_profile_page
374+ && ! is_network_admin ()
375+ && isset ( $ _POST ['role ' ] )
376+ && current_user_can ( 'promote_user ' , $ user_id )
377+ ) {
378+ $ role = sanitize_text_field ( wp_unslash ( $ _POST ['role ' ] ) );
379+ $ editable_roles = get_editable_roles ();
380+
381+ if ( '' === $ role || ! empty ( $ editable_roles [ $ role ] ) ) {
382+ $ user ->roles = $ role ? array ( $ role ) : array ();
383+ }
384+ }
385+
386+ return $ user ;
387+ }
388+
389+ /**
390+ * Filters user options for the edit screen when repopulating submitted values.
391+ *
392+ * @since 7.1.0
393+ * @access private
394+ *
395+ * @param mixed $result Value for the user's option.
396+ * @param string $option Name of the option being retrieved.
397+ * @param WP_User $user WP_User object of the user whose option is being retrieved.
398+ * @return mixed Filtered user option value.
399+ */
400+ function _get_user_edit_form_posted_option ( $ result , $ option , $ user ) {
401+ global $ _wp_user_edit_posted_options ;
402+
403+ if ( empty ( $ _wp_user_edit_posted_options ['user_id ' ] )
404+ || (int ) $ _wp_user_edit_posted_options ['user_id ' ] !== (int ) $ user ->ID
405+ || ! isset ( $ _wp_user_edit_posted_options ['options ' ][ $ option ] )
406+ ) {
407+ return $ result ;
408+ }
409+
410+ return $ _wp_user_edit_posted_options ['options ' ][ $ option ];
411+ }
412+
368413/**
369414 * Fetch a filtered list of user roles that the current user is
370415 * allowed to edit.
0 commit comments