HMVC framework for WordPress plugin development Download

WordPress Fuel Plugin

WordPress Fuel Plugin versus Flat WordPress Plugin


In this chapter, you'll write a simple WordPress plugin in flat PHP, and then refactor it to be more organized.

A simple Contact Form WordPress plugin in flat PHP

In this chapter, you'll build the simple contact form plugin using only flat PHP. This plugin creates the shortcode [simple_contact_form] which will insert a small contact form. There are only name, email, subject, and message fields and the email will be sent to the administrator account's email address. Writing in flat WordPress plugin is quick and dirty:

<?php
    /*
    Plugin Name: WP Simple Contact Form
    Description:  Just type [wp_simple_contact_form].
    Version: 1.0
    */
    class WPSimpleContactForm 
    {
        function __construct() 
        {
            // register shortcode
            add_shortcode( 'simple_contact_form', array( $this, 'shortcode' ) ); 
        }

        // SHORTCODE
        function shortcode() 
        {
            // if form was manually submitted
            if( !array_key_exists( 'submit', $_POST ) ) 
                    return $this->render_form();

            elseif( empty( $_POST['frn_email'] ) )
                    return $this->render_form( 'You forgot to include your email address!');

            elseif( empty( $_POST['frn_message'] ) )
                    return $this->render_form('You forgot to include a message!');

            else return $this->send_email();

        }

        // SEND EMAIL
        function send_email() 
        { 	
            // get the admin account's email address
            $to_email = get_option( 'admin_email' ); 

            // use default if no subject given
            $subject = ( empty( $_POST['frn_subject'] ) ? '(no subject)' : esc_attr( $_POST['frn_subject'] ) ); 		

            // use default if no proper name given
            $from_name = esc_attr( $_POST['frn_name'] );

            // use admin account's email address as sender if none given
            $from_email = esc_attr( $_POST['frn_email'] );

            // use admin account's email address as sender if none given
            $message = esc_attr( $_POST['frn_message'] );

            // build headers and send mail
            $headers = 'From: ' . $from_name . ' <' . $from_email . '>' . "\r\n";
            mail( $to_email, $subject, $message, $headers );

            return '<p class="frm-report">' . 'Your message was sent successfully!' . '</p>';
        }

        function render_form( $notify='' ) 
        { 
                // translated labels
                $your_name =  'Your name:';
                $your_email = 'Your email:';
                $subject = 'Subject:';
                $message = 'Message:'; 

                // build return string
                return "\r\n" . 
                        '
                        <style type="text/css">
                                .frm-report {}
                                .frm-forgot {
                                        background-color: #CD5C5C;
                                }
                                .frm-notify {
                                        padding-bottom: 1.5em;
                                }
                                .frm-notify span {
                                        color: #f00;
                                        border-bottom:1px dotted #f00;
                                }
                                .frm-wrapper {
                                        margin: 0;
                                        padding: 0;
                                        clear: both;
                                }
                                .frm-input-wrapper {}
                                .frm-input-wrapper label {
                                        width: 100px;
                                        float: left;
                                }
                                .frm-input-wrapper input {
                                        width:280px;
                                }
                                .frm-input-wrapper textarea {
                                        width:280px;
                                        height: 102px;
                                }
                                .frm-submit {}
                                .clear {
                                        height: 0;
                                        visibility: hidden;
                                        clear: both;
                                        display: block;
                                        width: auto;
                                }
                </style>

                        <div class="frm-wrapper">
                                <form action="" method="post">
                                ' . ( empty( $notify ) ? '' : '<div class="frm-notify"><span>' . $notify . '</span></div>' ) . '
                                <p id="frm-your-name-wrapper" class="frm-input-wrapper">
                                        <label for="frn_from_name">' . $your_name . '</label>
                                        <input type="text" name="frn_from_name" id="frn_from_name" value="' . ( isset( $_POST['frn_from_name'] ) ? esc_attr( $_POST['frn_from_name'] ) : '' ) . '" />
                                </p>

                                <p id="frm-from-email-wrapper" class="frm-input-wrapper">
                                        <label for="frn_from_email">' . $your_email . '</label>
                                        <input type="text" name="frn_from_email" id="frn_from_email" value="' . ( isset( $_POST['frn_from_email'] ) ? esc_attr( $_POST['frn_from_email'] ) : '' ) . '"' . ( empty( $_POST['frn_from_email'] ) && array_key_exists( 'submit', $_POST ) ? ' class="frm-forgot"' : '' ) . ' />
                                </p>

                                <p id="frm-subject-wrapper" class="frm-input-wrapper">
                                        <label for="frn_subject">' . $subject . '</label>
                                        <input type="text" name="frn_subject" id="frn_subject" value="' . (isset( $_POST['frn_subject'] ) ? esc_attr( $_POST['frn_subject'] ) : '' ) . '" />
                                </p>

                                <p id="frm-message-wrapper" class="frm-input-wrapper">
                                        <label for="frn_message">' . $message . '</label>
                                        <textarea name="frn_message" id="frn_message" cols="45" rows="5"' . ( empty( $_POST['frn_message'] ) && array_key_exists( 'submit', $_POST ) ? ' class="frm-forgot"' : '' ) . '>' . (isset( $_POST['frn_message'] ) ? esc_attr( $_POST['frn_message'] ) : '' ) . '</textarea>
                                </p>

                                <p id="frm-submit-wrapper">
                                        <input type="submit" name="submit" id="submit" value="Send" class="frm-submit"/>
                                </p>

                                <p class="frm-clear"></p>

                                </form>
                        </div>
                        ' . "\r\n";
        }

    } // end class

    new WPSimpleContactForm;
    ?>

That's quick to write, fast to execute, and, as your plugin functionality grows, difficult to maintain. There are several problems that need to be addressed:

  • Poor organization: Control logic, presentation and validation rules all in one place. If the plugin code grows, this single file will become increasingly unmaintainable. Where should you put code to handle a AJAX form submission? How should you set auto responder email template?
  • Difficult to reuse code: Since everything is in one PHP class, there's no way to reuse any part of the plugin.

Let's get to work on solving these problems.


Organizing the Plugin code using WordPress Fuel

The following is the WordPress Fuel plugin file. You can see that it is simple and clean. Input processing, validation, shortcode handling and presentation all isolated.

<?php
/* 
Plugin Name: WP Simple Contact Form
Plugin Slug: coremvc-simple-contact-form
Description: Simple Form to email. Send form submission to admin. Shortcode: [simple_contact_form][/simple_contact_form]
*/
require_once "init.php";
class WpSimpleContactForm_Plugin extends absMVC_Plugin
{
    /*
    * Unique Slug for every plugin
    * Must be one word without any special characters
    */
    protected $_plugin_slug = "wpsimplecontactform";
    
    /**
     * Initialize any front-end related code for this plugin
     * @uses absMVC_Shortcode
     */
    public function initFront()
    {
        $this->add_shortcode("simple_contact_form", "scoWPSimpleContactForm_ShortCode","render_form");
    }
}

new WpSimpleContactForm_Plugin(__FILE__);

The Shortcode logic is now stored in a separate class (scoForm), which is primarily a PHP class file (mvc\shortcodes\wpsimplecontactform\shortcode.php) that uses WordPress shortcode API:

scoWPSimpleContactForm_ShortCode: Shortcode Handler PHP Class

<?php
class scoWPSimpleContactForm_ShortCode extends absMVC_Shortcode
{
    public function render_form($shortcode_attributes,$content = null)
    {
        global $post;
        
        if(is_single($post))
        {
            $oPlugin = $this->getPlugin();
            $plugin_file = $oPlugin->getPluginFile();

            wp_enqueue_style('contact-simple-form-styles', plugins_url( '/assets/css/style.css', $plugin_file ),false,'1.1','all');

            return $oPlugin->dispatchRequest("form",array('shortcode_attributes' => (array)$shortcode_attributes));
        }
    }
}
?>

The Shortcode class enqueues CSS styles and dispatches the short code request to Form Controller which is primarily a PHP class file (mvc\controls\wpsimplecontactform\form.php) that uses WordPress shortcode API:


Form Controller

The following Form controller would render a page that simply contact form. It also handles the form submission process.

<?php
class wpsimplecontactform_form_controller extends absController
{	
    public function index()
    {
        if(Core::isPost())
        {
            $responseMessage = $this->_process();
            $this->ViewData('message',$responseMessage);
        }

        $this->View('form/index');
    }

    private $_data = null;

    private function _process()
    {
        $this->_data = $this->_request->getParams();
        if(isset($this->_data['submit_form_btn']) == false)
            return;

        //do validation stuff

        $this->_mail();
        return array('type' => 'success', 'message' => array('Thank you. Our representative will contact you shortly.'));

    }

    private function _mail()
    {
        $subject = "New Contact Request from ".$this->_data['full_name']."";

        $message = "<html><body><table cellpadding='0' cellspacing='0' width='100%'>";

        foreach($this->_data as $label => $value)
        {
            if($value != "")
            {
                $message .="<tr><td width='30%'>".clsSlug::slugToTitle($label)."</td><td width='70%' colspan='2'>".nl2br($value)."</td></tr>";
            }
        }
        $message .="</table></body></html>";

        @wp_mail(get_option('admin_email'), $subject, $message);
    }
}
?>

Controller refers simply to the area of your code that processes user input and prepares the response.

Isolating the Presentation

The code can immediately gain from separating the application "logic" from the code that prepares the HTML "presentation":

<div class="main_container"><div class="form_container">
        
        <?PHP if(isset($message)): ?>
        <ul class="system_messages" id="msg_flash_ul">
            <li id="li_msg" class="<?PHP echo $message['type']; ?>">
                    <span class="ico"></span>
                    <strong class="system_title">
                        
                    <?PHP foreach($message['message'] as $k => $message_text): ?>
                        <?PHP echo $message_text; ?><br />
                     <?PHP endforeach; ?>
                        
                    </strong>
            </li>
        </ul>
        <?PHP endif; ?>
        
        <form method="POST" class="rounded_form" action="<?PHP echo clsUri::currentURL(); ?>">
            <fieldset>
                
                <div class="field_box">
                        <span class="field_area">
                            <label>Your Name *</label>
                            <input type="text" id="full_name" name="full_name" value="<?PHP echo $row['full_name']; ?>">
                        </span>
                </div>
                
                <div class="field_box">
                        <span class="field_area">
                                <label>Email *</label>
                            <input type="text" id="email" name="email" value="<?PHP echo $row['email']; ?>">
                        </span>
                </div>
      
                <div class="field_box">
                        <span class="field_area">
                            <label>Subject *</label>
                             <input type="text" id="subject" name="subject" value="<?PHP echo $row['subject']; ?>">
                        </span>
                </div>
                
                <div class="field_box">
                        <span class="field_area">
                                <label>Message *</label>
                           <textarea id="message" name="message"><?PHP echo $row['message']; ?></textarea>
                        </span>
                </div>
       
                <div class="field_box">
                    <span class="field_area">
                          <input type="submit" value="Submit" id="submit_btn" class="form-btn-submit" name="submit_form_btn">
                          <span style="display:none;" id="msg_bottom" class="info_area bottom_info"></span>
                    </span>
                </div>
                
            </fieldset>
        </form>
    </div>
</div>


WordPress Fuel Plugin

The WordPress Fuel Plugin acts as a front controller and it's job is to initialize the WP Fuel engine and handles the request. Framework then uses the request URI to determine which controller to dispatch the request to.

  • Your WordPress plugin now has clear and organized code.
  • Application logic, presentation, and business logic, all are isolated.
  • This promotes code reusability and allows you to develop plugins rapidly