Opened 7 years ago
Last modified 5 years ago
#43734 new defect (bug)
user_profile_update_errors hook needs work-around to validate a to-be updated email address
Reported by: | BjornW | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | |
Component: | Users | Keywords: | |
Focuses: | docs | Cc: |
Description
The 'user_profile_update_errors' hook can be used to (in)validate (custom added) fields in the user_profile before these fields are saved.
As far as I know, the 'best-practice' to do this is, is by accessing the field using it's name in $_POST
. Grab it's value, do your thing and if this results in an error, add an error message to the $errors object and prevent the field from being saved to the database.
This does not work with the email field anymore (since WordPress version 4.9.0?), because $_POST['email']
is reset to the current value in the database in the function send_confirmation_on_profile_email()
. See: wp-includes/user.php
The reset of $_POST['email']
to the current email address in the database prevents the 'best-practice' of accessing a field's value through $_POST
because the new email address is now gone from $_POST
.
Why is there a reset on $_POST?
My assumption is:
Resetting $_POST['email']
to the current email address in the database is needed, because of the new flow in WordPres in which WordPress requests a user's confirmation of a proposed email change (by sending an email to the new address and requesting the user to clink a link to confirm the change) before saving the new email address.
Therefor the value in the form should (at least temporarily) not be changed until the user has confirmed the change in email address. The chosen solution is such that the new email address is temporarily saved in a user meta field with the name '_new_email' including a hash. This is then processed upon when the user clicks on the link in the email requesting the email change.
Solution
I don't have a good solution yet and by submitting this ticket I hope more people can have a look at this issue.
For now I'd suggest to update docs to include detailed information on how to use the user meta field _new_email['newemail']}} instead of {{{$_POST['email']
in the user_profile_update_errors hook.
Change History (5)
#2
in reply to:
↑ 1
@
7 years ago
Replying to soulseekah:
I think the deeper issue is that there's no straightforward way to prevent
send_confirmation_on_profile_email
from running without prevalidation. Like what if I want to prevent certain domains from being picked as a new e-mail? I should be able to prevent everything from triggering.
One way is to register
personal_options_update
andedit_user_profile_update
hooks and removesend_confirmation_on_profile_email
and then run it after validation. But that seems hacky.
I agree completely. Seems to me the current implementation warrants a better one taking these use cases into account. I guess we need to come up with a patch as a proof-of-concept?
This ticket was mentioned in Slack in #core by bjornw. View the logs.
6 years ago
#5
@
5 years ago
I'm running into the exact issue @soulseekah describes in a client project (a custom-build domain blacklist plugin). Through a lot of trickery I've managed to sabotage the 'send_confirmation_on_profile_email' email so it does not get sent. However, I feel this issue warrants a new hook, probably in the send_confirmation_on_profile_email()
function.
How about a filter hook called send_confirmation_on_profile_email
that receives a boolean value (send mail or not, initially set to true), and the current user object? I'll gladly write a patch to add this hook. It would make suppressing the email trivial.
I think the deeper issue is that there's no straightforward way to prevent
send_confirmation_on_profile_email
from running without prevalidation. Like what if I want to prevent certain domains from being picked as a new e-mail? I should be able to prevent everything from triggering.One way is to register
personal_options_update
andedit_user_profile_update
hooks and removesend_confirmation_on_profile_email
and then run it after validation. But that seems hacky.