Front End Login WordPress Plugin – Model View Controller (MVC) – Tutorial – Part Two
In Part One we introduced the Model-View-Controller (MVC) paradigm and used it to develop the “Front-End-Registration-Login” plugin. The development was not complete as we only implemented the login/logout functionality. In this part we will add the following:
- Change Password
- Oops .. I forgot my Password
- Register
This functionality will be added using the MVC scaffolding we put in place in Part One. No new classes or files are required. An understanding of the principles and code introduced in Part One is however essential to follow the development here.
Change My Password
This is the simplest functionality to implement. The scenario is a logged-in user who wants to change her password. We will provide a shortcode which can be embedded on a page. The new password has to satisfy our password requirements. Passwords ARE case sensitive, and should be at least six characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! @ # ? $ % ^ & * _ – ).
The View
First we add the shortcode “ferl_password_form“. To handle this shortcode, we add the “password_form” and “password_form_view” methods.
private function add_shortcodes() { add_shortcode('ferl_login_form', array( $this,'login_form' ) ); add_shortcode('ferl_password_form', array( $this,'password_form' ) ); }
See line 3 where the shortcode “ferl_password_form” is added.
public function password_form() { $this->load_css = true; $output = ''; if(!is_user_logged_in()) { $output = __('You must be signed in to change your password'); } else { // show the password form $current_user = wp_get_current_user(); $output = $this->password_form_view($current_user->user_login); } return $output; }
We make sure we have a logged-in user, and then pass the “user_login” string (aka username) to the method which actually produces the form.
private function password_form_view($username) { ob_start(); ?> <h3 class="ferl_header">Account: <?= $username ?></h3> <?php // show any error messages after form submission $this->show_error_messages(); $this->show_info_messages(); ?> <form id="ferl_password_form" class="ferl_form" action="" method="post"> <fieldset> <p> <label for="ferl_user_pass">Password</label> <input name="ferl_user_pass1" id="ferl_user_pass1" class="required" type="password"/> </p> <p> <label for="ferl_user_pass">Repeat Password</label> <input name="ferl_user_pass2" id="ferl_user_pass2" class="required" type="password"/> </p> <p> <input type="hidden" name="ferl_action" value="password" /> <input type="hidden" name="username" value="<?= $username ?>" /> <input type="hidden" name="ferl_password_nonce" value="<?php echo wp_create_nonce('ferl-password-nonce'); ?>"/> <input id="ferl_password_submit" type="submit" value="Change Password"/> </p> </fieldset> </form> <?php return ob_get_clean(); }
This method renders a standard form with a nonce etc.
The form looks like this:
Controller
When the form is submitted, the “ferl_action” is “password“. We add a line the Controller class init() method. This hands then off to the Model class.
private function init() { /* pass request parameters to the model */ $this->model->set_request_params($this->post_array, $this->get_array); /* handle the form posts */ if (isset($this->post_array['ferl_action'])): switch ($this->post_array['ferl_action']): case "login": add_action( 'init', array( $this->model, 'login_user' ) ); break; case "logout": add_action( 'init', array( $this->model, 'logout_user' ) ); break; case "password": add_action( 'init', array( $this->model, 'change_password' ) ); break; endswitch; endif; // $ferl_action }
Lines 16-18 handle the post from the change password form. The Model change_password method will then do the heavy lifting.
Model
This is where all the action happens. Basically, we need to make sure the passwords entered are valid. Once we get that, we change the password for the user.
public function change_password() { $pw_chars = array('!', '@', '#', '?', '$', '%', '^', '&', '*', '_', '-'); if ( ! empty( $this->post_array['username'] ) && wp_verify_nonce($this->post_array['ferl_password_nonce'], 'ferl-password-nonce') ) { $current_user = get_user_by('login',$this->post_array['username']); $pass1 = $this->post_array['ferl_user_pass1']; $pass2 = $this->post_array['ferl_user_pass2']; /* Password validation */ if ( strlen( $pass1 ) > 0 && strlen( $pass2 ) > 0 ) { if ( $pass1 == $pass2 ) { if ( strlen($pass1) < 6 ) { $this->wp_error->add('invalid_password',__('A password must be at least 6 characters long. Your password was not updated.')); } else { if ( ! ctype_alnum( str_replace($pw_chars, '', $pass1) ) ) { $this->wp_error->add('invalid_password',__("A password can only contain a alphanumeric characters and the following characters: <br />".implode (' ', $pw_chars)." <br/>Your password was not updated.")); } } } else { $this->wp_error->add('invalid_password',__('The passwords you entered do not match. Your password was not updated.')); } } else { $this->wp_error->add('invalid_password',__('A password must be at least 6 characters long. Your password was not updated.')); } /* retrieve all error messages */ $errors = $this->wp_error->get_error_messages(); /* Update user password if there are no errors */ if(empty($errors)) { wp_update_user( array( 'ID' => $current_user->ID, 'user_pass' => esc_attr( $pass1 ) ) ); $this->wp_info->add('updated_password',__('Your password has been updated.')); } } }
The $pw_chars array defined on line 2 are those characters we will allow in passwords in addition to the strict alpha-numeric ones. The function first validates the entered passwords, and if no errors are found it updates the user password in line 32.