As of WordPress 4.4, the action lostpassword_post
passes the $errors
object:
function wpse_185243_lastpassword_post( $errors ) {
if ( ! $captcha_valid /* The result of your captcha */ ) {
$errors->add( 'invalid_captcha', '<strong>ERROR:</strong> Try again sonny.' );
}
}
add_action( 'lostpassword_post', 'wpse_185243_lastpassword_post' );
Pre 4.4 legacy answer
Here’s the relevant code you’re referring to (retrieve_password()
in wp-login.php
):
function retrieve_password() {
$errors = new WP_Error();
// Some error checking
do_action( 'lostpassword_post' );
if ( $errors->get_error_code() )
return $errors;
// Some more code
/**
* Filter whether to allow a password to be reset.
*
* @since 2.7.0
*
* @param bool true Whether to allow the password to be reset. Default true.
* @param int $user_data->ID The ID of the user attempting to reset a password.
*/
$allow = apply_filters( 'allow_password_reset', true, $user_data->ID );
if ( ! $allow )
return new WP_Error('no_password_reset', __('Password reset is not allowed for this user'));
else if ( is_wp_error($allow) )
return $allow;
}
As you say, there’s no way to get hold of $errors
(it’s a local variable and is never passed to a filter/action – might be worth filing a feature request in a trac ticket).
However, it appears you can use allow_password_reset
to return a new WP_Error
, and WordPress will handle it in the same way as a core error:
function wpse_185243_lost_password_captcha( $result, $user_id ) {
if ( ! $captcha_valid /* The result of your captcha */ ) {
$result = new WP_Error( 'invalid_captcha', '<strong>ERROR:</strong> Try again sonny.' );
}
return $result;
}
add_filter( 'allow_password_reset', 'wpse_185243_lost_password_captcha', 10, 2 );