Front End Login WordPress Plugin – Model View Controller (MVC) – Tutorial – Part One

Pages: 1 2 3

The Scaffolding

In the plugins directory, create the folder drmagu-front-end-registration-login.

In this folder, create two files index.php and plugin-main.php.

<?php
// Silence is golden.
<?php
/*
Plugin Name: Front end wp registration & login
Plugin URI: http://www.drmagu.com/front-end-login-wordpress-plugin-model-view-controller-tutorial-part-one-1049.htm
Description: Allows front-end registration and login
Version: 0.9
Author: DrMagu
Author URI: http://www.drmagu.com
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
*/
namespace drmagu\front_end_registration_login;

/* only allow WP environment */
defined('ABSPATH') or die("Oops.  Not here buddy!");

/*
 * Setup the autoloader
 * Looks for class files in the "classes/" directory
 */

require_once (__DIR__.'/classes/Autoloader.class.php');
new Autoloader(__DIR__.'/classes/');

/* run the plugin */
new Main();  

/*
 * Main Plugin Class
 */

class Main {

	public function	__construct() {
		$this->main();
	}

	private function main() {

		/* limit the access */
		new LimitAdminAccess();

		/* login & logout functionality and more */
		$the_model = new Model();
		$the_view = new View($the_model, plugin_dir_url( __FILE__ ));
		new Controller($_POST, $_GET, $the_model, $the_view);
	}

}

Some things of note.  Line 12 defines the namespace for this plugin. Line 15 allows execution from the WordPress environment only.  Executable code are the two lines to get the “Autoloader” setup (line 23), and the construction of the “Main” object (line 26).

In the classes directory, we create an index.php file (same as in the main directory) and the following class files: Autoloader.class.php, Model.class.php, View.class.php, Controller.class.php and a special purpose class LimitAdminAccess.class.php.

The Autoloader class is rather straighforward

<?php
namespace drmagu\front_end_registration_login;

class Autoloader {

	private $class_path;

	public function __construct($class_path) {
		$this->class_path = $class_path;

		$this->init();
	}

	private function init() {
		spl_autoload_register(array($this, 'require_class'));
	}

	public function require_class($class) {
			/* strip any namespaces */
			$arr_class = explode('\\', $class);
			$class = end($arr_class);

			if ( is_file( $this->class_path.$class.'.class.php' ) )
			{
				require_once( $this->class_path.$class.'.class.php' );
			}
	}

}

The LimitAdminAccess class stops access to the standard WordPress back-end, as well as login and registration etc.

<?php
namespace drmagu\front_end_registration_login;

class LimitAdminAccess {

	public function __construct() {
		$this->add_actions();
	}

	private function add_actions() {
		add_action( 'login_head', array( $this, 'no_wp_login' ) );
		add_action( 'admin_init', array( $this, 'restrict_admin_with_redirect' ) );
		add_action( 'init', array( $this , 'disable_adminbar' ) );
		add_action( 'wp_logout', array( $this, 'go_home' ) );
	}

	/*
	* Redirect All trying to access native wp-login pages directly
	*/
	public function no_wp_login() {
		wp_redirect(home_url());
		exit;
	}

	/*
	* Restrict access to backend for all except ADMIN
	*/
	public function restrict_admin_with_redirect() {
		if( ! current_user_can('manage_options') && $_SERVER['PHP_SELF'] != '/wp-admin/admin-ajax.php' ) {
			wp_redirect( home_url() );
			exit;
		}
	}

	/*
	*  Removes Admin bar for all Except ADMIN
	*/
	public function disable_adminbar(){
		if( ! current_user_can('manage_options') ){
			show_admin_bar(false);
		}
	}

	/*
	* Redirect to home page at logout
	*/
	public function go_home(){
	  wp_redirect( home_url() );
	  exit();
	}
}

Note that the namespace is declared as the first line in each of these files.

Now that we have two working classes, we finish by putting in the scaffolding for the Model, View and Controller classes.

The Model class is used by both the Controller and the View classes.  It is responsible for the “business” logic of the application.  In our case, this will be the actual registration, login functionality, etc.

<?php
namespace drmagu\front_end_registration_login;

class Model {

	public function __construct() {

	}
}

The View class needs to obtain data from Model.  It is responsible for outputting to the browser screen, so styles are loaded when required.

<?php
namespace drmagu\front_end_registration_login;

class View {

	private $load_css = false;
	private $model;
	private $plugin_dir_url;

	public function  __construct(Model $model, $plugin_dir_url) {
		$this->model = $model;
		$this->plugin_dir_url = $plugin_dir_url;

		$this->init();
	}

	private function init() {
		add_action('init', array( $this, 'register_css' ) );
		add_action('wp_footer', array( $this, 'print_css' ) );
	}

	// register our form css
	public function register_css() {
		wp_register_style('ferl-form-css', $this->plugin_dir_url . '/css/forms.css');
	}

	// load our form css
	public function print_css() {
		// this variable is set to TRUE if the short code is used on a page/post
		if ( ! $this->load_css )
			return; // this means that the short code is not present, so we get out of here
		wp_print_styles('ferl-form-css');
	}
}

The forms.css file lives in the css sub-directory. For completeness we list it here (click to expand).

/** CSS for the Front End Forms **/
.ferl_form br { display:none; } /* hack cuz WP insists on adding <br /> tags after a closing </label> */
.ferl_form label { display: block;float: left; width: 130px; }
.ferl_form input[type="text"], .ferl_form input[type="password"],
.ferl_form input[type="email"] {
	margin-left: 10px;
	padding: 4px 8px;
	background: #f0f0f0;
	border: 1px solid #ccc;
}
.ferl_form input[type="text"]:focus, .ferl_form input[type="password"]:focus,
.ferl_form input[type="email"]:focus {
	border-color: #aaa;
}

.ferl_errors { padding: 8px; border: 1px solid #f50; margin: 0 0 15px; }
.ferl_info { padding: 8px; border: 1px solid #0f5; margin: 0 0 15px; }

The Controller class is aware of the $_POST and $_GET parameters coming from the browser.  It also has direct access to the Model and the View class.

<?php
namespace drmagu\front_end_registration_login;

/*
 * Handle the browser requests and route them
 * There are two requests types
 * -> respond to a form submission (POST)
 * -> respond to a GET request
 */
class Controller {
	private $post_array;
	private $get_array;
	private $view;
	private $model;

	public function __construct($post_array, $get_array, Model $model, View $view) {
		$this->post_array = $post_array;
		$this->get_array = $get_array;
		$this->view = $view;
		$this->model = $model;

		$this->init();
	}

	private function init() {
		/* here is where wp action hooks are defined for various scenarios */

	}
}

The scaffolding is now complete.  A this point, the plugin can be activated.  Of course, it won’t really DO anything, except preventing logins.  So before you lock yourself out, de-activate the plugin again.

Pages: 1 2 3

Leave a Reply

You must be logged in to post a comment.