Plugin Tutorial

Table of Contents

  1. Overview
  2. Installing the Stub Plugin
  3. Linking a URL to an Action
  4. Separate out HTML to a template
  5. Adding to the Admin Menu
  6. Overriding Actions
  7. Overriding Templates

Overview

This tutorial will show you how to create a plugin. The plugin will do the following:

  • Install itself by creating a database table and adding three records
  • Display a page
  • Set the page's title
  • Set the window's title
  • Pass some text to the page
  • Pass objects from the database to the page
  • Pass a notification message to the user

The page will look like this:

Installing the Stub Plugin

  1. Decide on a name for your plugin. The current naming convention for plugin names is all lower-case, letters and numbers only. The recommendation may change to include upper-case letters in the future. Do not include non-alphanumeric characters.

    Enter your plugin name below to make the rest of the tutorial clearer:

  2. Create a folder in mm/plugins of your Modern Merchant installation. Give it the name of your plugin. This will be your plugin's folder.
  3. Create a new file in your plugin's folder called Plugin.php. Paste this PHP code into the file:
    <?php
    /**
     * Sample plugin.
     */
    class sample_Plugin extends plugin_Base
    {
        function info()
        {
            return array(
                'title'   => 'Sample Plugin',
                'version' => '0.1',
                'author'  => 'Your Name',
                'url'     => 'http://www.example.com/',
                'depends' => array('mm'));
        }
    
        /**
         * Called automatically for each request if the plugin is active.
         */
        function init()
        {
        }
    
        /**
         * Called automatically when Modern Merchant is installed, and when user
         * requests that the plugin be installed.
         */
        function install()
        {
            $db = mm_getDatabase();
            $db->execute("DROP TABLE IF EXISTS mm_comment");
            $db->execute("
            CREATE TABLE mm_comment (
                id int not null auto_increment,
                subject varchar(255) not null,
                comment text,
                PRIMARY KEY (id)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8
            ");
            $db->execute("INSERT INTO mm_comment (subject, comment) VALUES (?,?)", array("morning", "It's too early"));
            $db->execute("INSERT INTO mm_comment (subject, comment) VALUES (?,?)", array("coffee", "Double Soy Latte"));
            $db->execute("INSERT INTO mm_comment (subject, comment) VALUES (?,?)", array("wifi", "WiFi Required"));
            return true;
        }
    
        /**
         * Called automatically when user requests that the plugin to be uninstalled.
         */
        function uninstall()
        {
            $db = mm_getDatabase();
            $db->execute("DROP TABLE IF EXISTS mm_comment");
            return true;
        }
    }
    
  4. Change the class name: replace "sample" with your plugin's name.
  5. Change the 'title' element returned from the info() method.
  6. With a browser, visit the Modern Merchant administrative interface. Navigate to Configuration -> Plugins. You should see your plugin listed there.
  7. Click install next to your plugin. This installs and activates your plugin.

Linking a URL to an Action

  1. Copy this skeleton code and paste into a file called Controller.php, saved to your plugin's folder:
    <php
    class sample_Controller extends mvc_PublicController
    {
        function runShowAction()
        {
            echo "Hello, world!";
            return $this->goToView();
        }
    }
    
  2. With a web browser, go to the web site's home page, for instance, http://www.example.com/, then change the address so that it ends with ?a=sample.show, replacing 'sample' with your plugin's name.
  3. If your plugin is going to have a public facing interface and an admin interface, you should have two separate controllers. The admin controller should go inside a folder called sample/admin. The file should also be called Controller.php, and the class should be called sample_admin_Controller. Requests that have a=sample_admin in them will go to the sample_admin_Controller.

Putting the HTML in a separate template

To separate out your View from the Controller, create a folder inside your plugin directory called sample/templates. Then, add a file called sample/templates/show.php to the templates folder.

Paste the following code into the file:

sample/templates/show.php:
<p>Greeting: <?php ph($this->greeting) ?></p>

<?php foreach($this->comments as $comment): ?>
<fieldset>
	<legend><?php ph($comment->subject) ?></legend>
	<?php ph($comment->comment) ?>
</fieldset>
<?php endforeach ?>

Next, you'll create your plugin's primary business model. Copy and paste this code into a file called Comment.php:

sample/Comment.php:
<?php
class sample_Comment extends mvc_Model {
    public $id;
    public $subject;
    public $comment;
}

Copy and paste this code into a file called CommentDAO.php:

<?php
class sample_CommentDAO extends mvc_DataAccess {
}

Back in the controller, change the runShowAction() method so that it looks like this:

<php
class sample_Controller extends mvc_PublicController
{
    function runShowAction() {
        // Fetch data from database and pass it to the template
        $dao = new sample_CommentDAO;
        $this->comments = $dao->find();              // Get all comments

        $this->title = "'Show' Action";             // Set the page (<h1>) title
        $this->addNotice("Something happened.");    // Send a notice to the user
        $this->greeting = "Hello, world!";          // Send some data to the template
    }
}

The first two lines within rowShowAction() will fetch all the records from the mm_sample database table, return them as objects, and assign them to a template variable called $samples.

The $this->title is a special template variable that sets the page's <h1> title.

When $this->addNotice() is called, the theme will display the message on the page when it is displayed, even if the next page occurs after a redirect.

In addition to $this->addNotice(), there is a method called $this->addWarning() that is for sending an error message to the user. The site's theme should display the warning message differently that a notice.

The last line in the function assigns a string to a new template variable called $this->greeting.

Here is the resulting page again, annotated with the code that assigns the page's content:

Adding a menu item to the Administrator Menu

To add a menu item to the Adminstrator menu, just add a line of code to your plugin's init() method:

sample/Plugin.php
<?php
class sample_Plugin
{
    //...

    function init()
    {
        mvc_Hooks::registerMenuItem(array(
            'path'  => 'admin/website/sample',
            'action'=>'sample.transactions',
            'label' => 'Authnet Transactions'));
    }
}

Overriding Actions

Sometimes, plugins need to override actions that are normally executed by other plugins. Modern Merchant's hook system makes this possible. For instance, if you want your plugin to override the cart.cart action (that's the action that displays the cart), you would use the hook system to map you own action to the cart.cart address.

While the hook system doesn't allow you to override individual actions directly, it does allow you to override entire controllers. With a bit of work, it is possible to override only specific actions of the controller, while passing control to the original controller for the remaining actions.

In the future, Modern Merchant will allow plugins to override individual actions without overriding the entire controller.

sample/Plugin.php:
<?php
class sample_Plugin
{
    //...

    function init()
    {
        $plugin_name = 'cart';
        $object_or_classname = 'sample_Controller';

        mvc_Hooks::registerController($plugin_name, $object_or_classname);
    }
}
sample/Controller.php:
<?php
class sample_Controller extends cart_Controller
{
    function runCartAction() {
        // Copy the code from cart_Controller::runShowAction(),
        // then customize it here
    }
}
Now, when the cart.cart action is executed, the code in sample_Controller::runCartAction() is executed instead of the code in cart_Controller::runCartAction().

Overriding Templates

Sometimes, you want to override templates from other plugins. Using the technique for overriding actions, described above, it is possible to accomplish this.

In the future, Modern Merchant will allow you to override templates directly, without overriding controllers and actions first.

sample/Plugin.php:
<?php
class sample_Plugin
{
    //...

    function init()
    {
        $plugin_name = 'cart';
        $object_or_classname = 'sample_Controller';

        mvc_Hooks::registerController($plugin_name, $object_or_classname);
    }
}
sample/Controller.php:
<?php
class sample_Controller extends cart_Controller
{
    function runCartAction() {
        $result = parent::runShowAction();
        return $this->goToView('sample.cart');
    }
}
sample/templates/cart.php:
<?php
/* Copy mm/plugins/cart/templates/cart.php to this file, then
customize it here. */