Skip to content

Commit 021a33a

Browse files
rootroot
authored andcommitted
Fix for retaining user info in user edit after submit
1 parent 8510818 commit 021a33a

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

src/wp-admin/includes/user.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ 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+
229237
return $errors;
230238
}
231239

@@ -249,6 +257,114 @@ function edit_user( $user_id = 0 ) {
249257
return $user_id;
250258
}
251259

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+
319+
/**
320+
* Gets the form fields responsible for a failed user update.
321+
*
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.
325+
*
326+
* @since 7.1.0
327+
* @access private
328+
*
329+
* @param WP_Error $errors Validation errors from `edit_user()`.
330+
* @return string[] Array of field names that should be excluded from the save.
331+
*/
332+
function _get_edit_user_error_fields( $errors ) {
333+
$error_fields = array();
334+
335+
foreach ( $errors->get_error_codes() as $code ) {
336+
$mapped_fields = array();
337+
338+
foreach ( $errors->get_all_error_data( $code ) as $data ) {
339+
if ( is_array( $data ) && ! empty( $data['form-field'] ) ) {
340+
$mapped_fields[] = $data['form-field'];
341+
}
342+
}
343+
344+
if ( empty( $mapped_fields ) ) {
345+
switch ( $code ) {
346+
case 'invalid_username':
347+
case 'user_login':
348+
$mapped_fields[] = 'user_login';
349+
break;
350+
case 'nickname':
351+
$mapped_fields[] = 'nickname';
352+
break;
353+
}
354+
}
355+
356+
if ( empty( $mapped_fields ) ) {
357+
return array();
358+
}
359+
360+
foreach ( $mapped_fields as $field ) {
361+
$error_fields[ $field ] = true;
362+
}
363+
}
364+
365+
return array_keys( $error_fields );
366+
}
367+
252368
/**
253369
* Fetch a filtered list of user roles that the current user is
254370
* allowed to edit.

0 commit comments

Comments
 (0)