Изменение страниц восстановления пароля в 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 ), $redirect_url );
		$to = add_query_arg( 'key', esc_attr( $key ), $redirect_url );
 
		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;
 
	}
 
}

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

Подпишитесь, чтобы раз в неделю получать свежие статьи с блога по email.

По теме

Комментарии 13

  • Дмитрий21 ноября 2016 в 19:11 #

    Миша, привет.
    Отличная серия постов по форме входа на сайт.
    Работает всё, за исключением одного:

    Почему-то не корректно работает форма сброса пароля.
    1. Когда ввожу в форме сброса пароля любой адрес полный, то появляется форма WP с сообщением "Пользователей с таким адресом e-mail не зарегистрировано."
    2. Если ввожу любой текст в поле для e-mail, то тоже форма WP "Неверное имя пользователя или e-mail."
    В представленном коде не нашел таких сообщений.
    Может тут части кода нет для этой цели, поэтому берется встроенная форма?

    В представленном примере в видео этот момент работает правильно.

    • Дмитрий22 ноября 2016 в 20:11 #

      Миша, а что по этому поводу?

      • Миша22 ноября 2016 в 23:11 #

        У меня всё ок

        • Дмитрий22 ноября 2016 в 23:11 #

          Может это потому-что я использовал стартовую тему пустую при разработке?
          А вы применили в уже готовой теме.
          И в коде нет этих фраз к тому же...

          • Миша24 ноября 2016 в 08:11 #

            в WordPress они есть.

            Я применил в twenty fifteen — можете попробовать в ней, но не уверен, что причина в теме (вы же использовали пустую).

            • Дмитрий25 ноября 2016 в 22:11 #

              Всё заработало. Случайно часть кода не скопировал.

              Возник вопрос:

              Я вызываю форму входа через шорткод.
              Хочу теперь убрать лейблы к input и вставить placeholder.
              Я открыл wp-login.php и добавил в два инпута свои placeholder="текст", но они не отобразились.
              Если в браузере изменить код, то все работает.

              Т.е. базовые параметры инпутов подменяются что ли другими параметрами?
              Подскажите пожалуйста, как сделать, чтобы placeholder появился?

  • Дмитрий21 ноября 2016 в 23:11 #

    И еще такие вопросики:
    - можно ли убрать перезагрузку страницы при работе с формой?
    - и как сделать запрет (редирект) в url на всё, что начинается с "wp-" (wp-admin, wp-login и аналогичные)?

  • Дмитрий22 ноября 2016 в 00:11 #

    с запретом и редиректом разобрался)

  • Дмитрий22 ноября 2016 в 00:11 #

    если следовать рекомендациям на блогах (везде одно и тоже) и вставить в functions.php код ниже, то форма входа перестает работать:

    /*wp-admin, ошибка 404*/
    add_action( 'init', 'blockusers_init' );
     function blockusers_init() {
     if ( is_admin() && ! current_user_can( 'administrator' ) &&
     ! ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
     wp_redirect( '404' );
     exit;
     }
     }
     
     /*wp-login.php, ошибка 404*/
    function redirect_login_page() {  
        $page_viewed = basename($_SERVER['REQUEST_URI']);  
     
        if( $page_viewed == "wp-login.php?pass=1" ) {  
            wp_redirect( '404' );  
            exit;  
        }  
    }  
    add_action('init','redirect_login_page');

    Миша, как с твоей формой выйти из этого положения, сохранив редирект с wp-....?

Оставить комментарий / вопрос

phpjsHTMLCSSSQLПросто код
  Для того, чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или авторизуйтесь на сайте.
Получайте новости блога по email или следите за мной в социальных сетях.
  • Миша: Привет, ну либо через Javascript, либо через save_post хук, скорее второе.

  • Дмитрий: Миша, а возможно ли задать условие, что если существует meta_key, то соответствующая таксономия будет нажата в метабоксе...

  • Дмитрий: Спасибо за подсказку. Получилось передать сразу нужный meta_key через value в hidden input.

  • Артем: Вот про сей хук я запамятовал)) Спасибо!

  • Миша: Думаю, что $mail_2 - пустая переменная по той простой причине, что $post->ID не существует. Глобальная переменная $po...