Documentation

Custom plugins

Presentation

Plugins make it possible to modularize the development of web applications. They make it possible in particular to factorize processing which must be done systematically at the start or at the end of all accesses.

This can be, for example, a plugin which checks that certain URLs are only accessible to authenticated users, and which will be executed before the processes reach the controllers; if the user is not authenticated, the plugin will redirect him to the authentication page, and the controller will not even be executed.
This can be a plugin which is executed at the end of the processing, to set template variables which are necessary for all the pages.
The possibilities are limitless…

Plugins can even manipulate framework data, which gives them the ability to change the controller or the action that will be executed, as well as the parameters that will be passed to it.

Development

Here is an example of a plugin:

class CheckPlugin extends \Temma\Web\Plugin {
    public function plugin() {
        // we set a template variable
        $this['checked'] = true;
    }
}

As can be seen in this example, plugins inherit from the \Temma\Web\Plugin parent class, which itself derives from the \Temma\Web\Controller class. Plugins are therefore controllers with just an additional capacity.
A plugin can therefore also be used as a controller, and a controller can also be used as a plugin.

In this example, we have defined a plugin() method, which will be executed when the plugin is called. It is therefore the configuration that will determine whether the object is a pre-plugin or a post-plugin.

To transmit data between plugins, or between plugins and the controller (and vice versa), template variables must be used. If a plugin sets a template variable, it will be accessible by all the plugins/controllers that follow in the execution chain.

So that the same object (whether it is only a plugin, or controller+plugin) can be both a pre-plugin and a post-plugin, by executing different code depending on the moment of its execution, we can define preplugin() and postplugin() methods.

  • When a plugin is executed in the PRE action chain, Temma first looks to see if it has a method named preplugin(). If so, it is executed; otherwise, we execute the plugin() method.
  • When a plugin is executed in the POST chain of actions, Temma first looks to see if it has a method named postplugin(). If so, it is executed; otherwise we execute the plugin () method.

Here is an example of a controller that is able to act as a pre-plugin and as a post-plugin, in addition to having several actions:

class Page extends \Temma\Web\Plugin {
    protected $_temmaAutoDao = true;

    // URL verification pre-plugin
    public function preplugin() {
        if (!$this->_checkUrl()) {
            return $this->httpError(404);
        }
        $this['checked'] = true;
    }

    // post-plugin for reprocessing variables before sending to the template
    public function postplugin() {
        $dirtyData = $this['dirtyData'];
        $cleanData = htmlspecialchars($dirtyData);
        $this['cleanData'] = $cleanData;
    }

    // root action
    public function index() {
        $this['pages'] = $this->_dao->search();
    }

    // additional action
    public function show($id) {
        $this['page'] = $this->_dao->get($id);
    }

    // private method
    private function _checkUrl() {
        // ...
        return (true);
    }
}

Handling of plugins and controller

The plugins and the controller can dynamically modify the information that the framework uses to determine which plugins/controller to run.

Modifying plugins

In a plugin method or a controller method (initialization, action or finalization), it is possible to retrieve the complete list of plugins, and to update it.

This is done through the $this->_loader->config object, which offers the plugins attribute, readable and writable. This attribute directly contains the array of plugins as defined in the temma.json file (see the configuration documentation).

If you change the plugins configuration, you may need to return an EXEC_RESTART or EXEC_REBOOT status, to force Temma to rerun the plugins chain.

Here is an example of a pre-plugin that reverses the order of the post-plugins.

class ReverseExamplePlugin extends \Temma\Web\Plugin {
    public function preplugin() {
        // retrieve the list of plugins
        $plugins = $this->_loader->config->plugins;

        // inversion of post-plugins
        $plugins['_post'] = array_reverse($plugins['_post']);

        // update the list of plugins
        $this->_loader->config->plugins = $plugins;
    }
}
Controller modification

In a plugin method or a controller method (initialization, action or finalization), it is possible to access the following information, and to modify it:

  • The name of the controller to run.
  • The name of the action to perform.
  • The parameters supplied to the action.

All this information can be accessed by the $this->_loader->request object, which offers the following methods:

  • getController(): Returns the name of the controller that will be executed. Identical to the $this['CONTROLLER'] template variable.
  • getAction(): Returns the name of the action that will be executed. Identical to the $this['ACTION'] template variable.
  • getNbrParams(): Returns the number of parameters.
  • getParams(): Returns the list of parameters.
  • getParam(int $index, [$default]): Returns the parameter whose index is given as a parameter. A default value can be passed as the second parameter; it will be returned if the requested parameter is not defined.
  • setController(string $name): Sets the name of the controller to run.
  • setAction(string $name): Defines the name of the action to run.
  • setParams(array $params): Defines the list of parameters.
  • setParam(int $index, string $value): Sets the value of a parameter whose index is provided.

Warning: If you modify the controller and/or the action with the setController() and setAction() methods, remember to update the corresponding template variables $this['CONTROLLER'] and $this['ACTION'], as well as $this['URL'].


Here is an example of a simplistic pre-plugin that extracts the language at the beginning of the URL.
For example, for a URL /en/article/show/123/my-article, the plugin will put "en" in the template variable $this['lang'], then do what it takes for Temma to do as if the received URL had been /article/show/123/my-article.

class LangExamplePlugin extends \Temma\Web\Plugin {
    public function preplugin() {
        // retrieve the language
        $lang = $this['CONTROLLER'];
        // retrieve the controller
        $newController = $this['ACTION'];
        // retrieve the parameters
        $params = $this->_loader->request->getParams();
        // extract the action and shift the parameters
        $newActions = array_shift($params);

        // update the data in Temma
        $this->_loader->request->setController($newController);
        $this->_loader->request->setAction($newAction);
        $this->_loader->request->setParams($params);
        // update the template variables
        $this['lang'] = $lang;
        $this['CONTROLLER'] = $newController;
        $this['ACTION'] = $newAction;
        $this['URL'] = substr($this['URL'], strlen($lang));
    }
}
Previous: Plugins
Next: Cache plugin

Table of Contents