Изменение страниц восстановления пароля в WordPress.

На прошлой неделе я уже опубликовал урок о том, как создать собственную форму авторизации в WordPress. Урок был очень простой и, казалось бы, надо идти по увеличению сложности и заняться формой регистрации.. но нет, сейчас мы рассмотрим самую сложную часть, связанную со страницами восстановления пароля — именно страницами, потому что в принципе их две — та, на которой вы вводите свой email и та, на которой вы устанавливаете новый пароль.

Однако я в свою очередь сделаю всё возможное, чтобы этот урок упростить.

Небольшая видео-демонстрация того, что мы сейчас будем делать:

На самом деле и тема и сам код довольно интересны, кроме того, я не встречал ещё хороших уроков об этом. Есть один урок на енвато, состоящий из двух частей, каждая из которых в свою очередь состоит из трёх шагов, у меня самого голова кругом пошла, когда я начал там разбираться.

Так что у меня была идея сделать этот пост премиумом, но так как идей и тем для платных постов пока что полно, я передумал.

Ну хватит болтовни, урок состоит из двух шагов, в первом мы создаём шорткод, а во втором — настраиваем редиректы и отправку письма. Весь код можете спокойно отправить в functions.php текущей темы.

Шаг 1. Шорткод для формы восстановления пароля

Прежде всего вставьте этот код.

add_shortcode( 'misha_custom_passreset', 'misha_render_pass_reset_form' ); // шорткод [misha_custom_passreset]
 
function misha_render_pass_reset_form() {
 
 	// если пользователь авторизован, просто выводим сообщение и выходим из функции
	if ( is_user_logged_in() ) {
		return sprintf( "Вы уже авторизованы на сайте. <a href='%s'>Выйти</a>.", wp_logout_url() );
	}
 
	$return = ''; // переменная, в которую всё будем записывать
 
	// обработка ошибок, если вам нужны такие же стили уведомлений, как в видео, CSS-код прикладываю чуть ниже
	if ( isset( $_REQUEST['errno'] ) ) {
		$errors = explode( ',', $_REQUEST['errno'] );
 
		foreach ( $errors as $error ) {
			switch ( $error ) {
				case 'empty_username':
					$return .= '<p class="errno">Вы не забыли указать свой email?</p>';
					break;
				case 'password_reset_empty':
					$return .= '<p class="errno">Укажите пароль!</p>';
					break;
				case 'password_reset_mismatch':
					$return .= '<p class="errno">Пароли не совпадают!</p>';
					break;
				case 'invalid_email':
				case 'invalidcombo':
					$return .= '<p class="errno">На сайте не найдено пользователя с указанным email.</p>';
					break;
			}
		}
	}
 
	// тем, кто пришёл сюда по ссылке из email, показываем форму установки нового пароля
	if ( isset( $_REQUEST['login'] ) && isset( $_REQUEST['key'] ) ) {
 
		$return .= '<h3>Укажите новый пароль</h3>
			<form name="resetpassform" id="resetpassform" action="' . site_url( 'wp-login.php?action=resetpass' ) . '" method="post" autocomplete="off">
				<input type="hidden" id="user_login" name="login" value="' . esc_attr( $_REQUEST['login'] ) . '" autocomplete="off" />
				<input type="hidden" name="key" value="' . esc_attr( $_REQUEST['key'] ) . '" />
         			<p>
					<label for="pass1">Новый пароль</label>
					<input type="password" name="pass1" id="pass1" class="input" size="20" value="" autocomplete="off" />
				</p>
				<p>
					<label for="pass2">Повторите пароль</label>
					<input type="password" name="pass2" id="pass2" class="input" size="20" value="" autocomplete="off" />
				</p>
 
				<p class="description">' . wp_get_password_hint() . '</p>
 
				<p class="resetpass-submit">
					<input type="submit" name="submit" id="resetpass-button" class="button" value="Сбросить" />
				</p>
			</form>';
 
		// возвращаем форму и выходим из функции
		return $return;
	}
 
	// всем остальным - обычная форма сброса пароля (1-й шаг, где указываем email)
	$return .= '
		<h3>Забыли пароль?</h3>
		<p>Укажите свой email, под которым вы зарегистрированы на сайте и на него будет отправлена информация о восстановлении пароля.</p>
		<form id="lostpasswordform" action="' . wp_lostpassword_url() . '" method="post">
			<p class="form-row">
				<label for="user_login">Email</label>
				<input type="text" name="user_login" id="user_login">
			</p>
 			<p class="lostpassword-submit">
				<input type="submit" name="submit" class="lostpassword-button" value="Отправить" />
			</p>
		</form>';
 
	// возвращаем форму и выходим из функции
	return $return;
}

Если код выше вам понятен, то вы заметили, что у нас будет одна страница WordPress для восстановления пароля — и когда мы указываем email для получения письма, и когда мы задаём новый пароль.

Поэтому теперь уже в админке WordPress переходим в Страницы > Добавить новую и вставляем в неё наш шорткод [misha_custom_passreset].

Если код из этой статьи вас пугает, рекомендую сделать всё 1 в 1, как на скриншоте.

Создаём произвольную страницу сброса пароля в WordPress

После того, как я разлогинился (вышел из сайта) и перешёл непосредственно на эту страницу, у меня получилось следующее.

Форма сброса пароля при помощи шорткода

Ах да, чуть не забыл про CSS, вот он:

.errno{
	background-color: #f4f4f4;
	padding: 10px 20px;
	border-left: 5px solid #fe0000;
}
.errno.success{
	border-left-color:#0bb80b;
}

Шаг 2. Редиректы, отправка ссылки на восстановление пароля.

А теперь код поинтереснее, и самое ужасное, что вам придётся настроить его под себя. Шучу, на самом деле ничего страшного тут не будет, единственное, что нужно сделать, это в начале каждой функции поменять ярлыки (slug) URL страницы восстановления пароля и страницы входа (прошлый урок) на те значения, которые решили использовать вы.

Если же вы так же создали у себя страницы с ярлыками forgot-pass и login, то вообще ничего менять не нужно.

/*
 * перенаправляем стандартную форму
 */
add_action( 'login_form_lostpassword', 'misha_pass_reset_redir' );
 
function misha_pass_reset_redir() {
	// если используете другой ярлык страницы сброса пароля, укажите здесь
	$forgot_pass_page_slug = '/forgot-pass';
	// если используете другой ярлык страницы входа, укажите здесь
	$login_page_slug = '/login';
	// если кто-то перешел на страницу сброса пароля
	// (!) именно перешел, а не отправил формой,
	// тогда перенаправляем на нашу кастомную страницу сброса пароля
	if ( 'GET' == $_SERVER['REQUEST_METHOD'] && !is_user_logged_in() ) {
		wp_redirect( site_url( $forgot_pass_page_slug ) );
		exit;
	} else if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
    		// если же напротив, была отправлена форма
    		// юзаем retrieve_password()
    		// которая отправляет на почту ссылку сброса пароля
    		// пользователю, который указан в $_POST['user_login']
		$errors = retrieve_password();
		if ( is_wp_error( $errors ) ) {
            		// если возникли ошибки, возвращаем пользователя назад на форму
            		$to = site_url( $forgot_pass_page_slug );
            		$to = add_query_arg( 'errno', join( ',', $errors->get_error_codes() ), $to );
        	} else {
            		// если ошибок не было, перенаправляем на логин с сообщением об успехе
            		$to = site_url( $login_page_slug );
            		$to = add_query_arg( 'errno', 'confirm', $to );
        	}
 
		// собственно сам редирект
        	wp_redirect( $to );
        	exit;
	}
}
 
/*
 * Манипуляции уже после перехода по ссылке из письма
 */
add_action( 'login_form_rp', 'misha_to_custom_password_reset' );
add_action( 'login_form_resetpass', 'misha_to_custom_password_reset' );
 
function misha_to_custom_password_reset(){
 
	$key = $_REQUEST['key'];
	$login = $_REQUEST['login'];
	// если используете другой ярлык страницы сброса пароля, укажите здесь
	$forgot_pass_page_slug = '/forgot-pass';
	// если используете другой ярлык страницы входа, укажите здесь
	$login_page_slug = '/login';
 
	// проверку соответствия ключа и логина проводим в обоих случаях
	if ( ( 'GET' == $_SERVER['REQUEST_METHOD'] || 'POST' == $_SERVER['REQUEST_METHOD'] )
		&& isset( $key ) && isset( $login ) ) {
 
		$user = check_password_reset_key( $key, $login );
 
		if ( ! $user || is_wp_error( $user ) ) {
			if ( $user && $user->get_error_code() === 'expired_key' ) {
				wp_redirect( site_url( $login_page_slug . '?errno=expiredkey' ) );
			} else {
				wp_redirect( site_url( $login_page_slug . '?errno=invalidkey' ) );
			}
			exit;
		}
 
	}
 
	if ( 'GET' == $_SERVER['REQUEST_METHOD'] ) {
 
		$to = site_url( $forgot_pass_page_slug );
		$to = add_query_arg( 'login', esc_attr( $login ), $to );
		$to = add_query_arg( 'key', esc_attr( $key ), $to );
 
		wp_redirect( $to );
		exit;
 
	} elseif ( 'POST' == $_SERVER['REQUEST_METHOD'] ) {
 
		if ( isset( $_POST['pass1'] ) ) {
 
 			if ( $_POST['pass1'] != $_POST['pass2'] ) {
				// если пароли не совпадают
				$to = site_url( $forgot_pass_page_slug );
 
				$to = add_query_arg( 'key', esc_attr( $key ), $to );
				$to = add_query_arg( 'login', esc_attr( $login ), $to );
				$to = add_query_arg( 'errno', 'password_reset_mismatch', $to );
 
				wp_redirect( $to );
				exit;
			}
 
			if ( empty( $_POST['pass1'] ) ) {
				// если поле с паролем пустое
 				$to = site_url( $forgot_pass_page_slug );
 
				$to = add_query_arg( 'key', esc_attr( $key ), $to );
				$to = add_query_arg( 'login', esc_attr( $login ), $to );
				$to = add_query_arg( 'errno', 'password_reset_empty', $to );
 
				wp_redirect( $to );
				exit;
			}
 
			// тут кстати вы можете задать и свои проверки, например, чтобы длина пароля была 8 символов
			// с паролями всё окей, можно сбрасывать
			reset_password( $user, $_POST['pass1'] );
			wp_redirect( site_url( $login_page_slug . '?errno=changed' ) );
 
		} else {
			// если что-то пошло не так
			echo "Что-то пошло не так.";
		}
 
		exit;
 
	}
 
}

Ну вот и всё, ссылки на описание некоторых из используемых функций вы найдёте чуть ниже под статьей. Кроме того, если у вас возник вопрос, вы всегда можете оставить его в комментариях, и он не останется без внимания.

Миша Рудрастых Разработчик WordPress WooCommerce

Миша Рудрастых

Впервые познакомился с WordPress в 2009 году, и после двух лет мучений с Joomla и самописными движками это был просто бальзам на душу. С 2014 года меня можно встретить на WordCamp — официальной конфе по WP в Москве, иногда там выступаю. Также в настоящее время веду курсы по WordPress в Epic Skills в Питере.

По теме