• Increase font size
  • Default font size
  • Decrease font size
Home Software PHK PHK and plugins

PHK and plugins

E-mail Print
Read : 7,721 times
(0 votes, average 0 out of 5)



1. Introduction
2. Reserved methods
     2.1. Constructor
     2.2. The _webinfo() method
3. A basic example


1 - Introduction

The architecture we present here is based on the 'plugin' , 'inversion of control', or 'dependency injection' design patterns. If you want to know more about the theory, you may find it here.

Actually, after all this theory is thrown away, it becomes simpler ;) :

  • it provides a way to extend a base software.
  • An extension is called a plugin.
  • In order to communicate with the base software, a plugin must implement a given interface.
  • This interface acts as a contract between the base software and the plugin, and is generally defined by an abstract class extended by the plugin's code.

Such an architecture is very common. It is used by Apache, PHP, Firefox... Most software accepting third-party extensions use this pattern.

As a package format, PHK is a tool of choice to implement a plugin architecture, as it is much easier to manage a plugin as a single file, rather than as a set of files. So, in order to make it still easier, PHK provides a mechanism specifically intended for plugins. If we use our old-fashioned term of 'entry point', we can say that, typically, a library does not define any entry point, a program defines one entry point, and a plugin defines a whole set of entry points. In PHK-compliant plugins, these entry points are implemented as methods in a given class. The methods' names are generally defined by an abstract class (or by an interface).

[:Note] In a typical configuration, a PHK archive used as a plugin is always included from another script, and never directly executed, either in CLI or web mode.

How it works : when a PHK archive is included, if the 'plugin_class' option is defined, an instance of this class is automatically created. The calling code can then get this object using the PHK::plugin() static method.

2 - Reserved methods

By convention, in a plugin, the method names starting with an underscore are reserved for PHK. So, when implementing a plugin system, avoid such names for your own methods.

2.1 - Constructor

The class constructor (__construct) receives the PHK package's mount point as argument.

2.2 - The _webinfo() method

This method is optional.

When the webinfo 'Info' page is displayed, or when the CLI '@techinfo' command is run, PHK looks for a '_webinfo()' method in the package's plugin (if it is defined). If this method exists, it is called and must display some information about the plugin.

Prototype :

void _webinfo(boolean $html);

where the $html argument informs the method wether it must display its result as HTML or plain text.

3 - A basic example

First, we define a plugin interface. This interface contains only one method, a sort of output filter supposed to display a string. Note that there is no limit to the number of methods a plugin can provide.

Here is the corresponding abstract class :

abstract class DisplayPlugin
{
    public function display($string);
}

Now, we know that every plugin must define this method in a class derived from this base class. Here is such a class :

class UpperDisplay extends DisplayPlugin
{
    //-- Display the string in uppercase

    public function display($string)
    {
        echo strtoupper($string)."\n";
    }

    //-- Information

    public function _webinfo($html)
    {
        $text='This plugin implements an all-uppercase display plugin.';
        if ($html) echo "<p>$text</p>";
        else echo "$text\n";
    }

}

Before building the archive, we need to specify which class implements the plugin interface. This is done by inserting the following option in the PSF file :

plugin_class: UpperDisplay

Then, we build the plugin package. It only contains the class file and defines the plugin_class option. Here is a basic PSF to generate the package :

add DisplayPlugin.php

%options

name:           Upper Display plugin
plugin_class: UpperDisplay

Now, in the base software, we load a plugin and use it to display a string :

class Display
{
    private $style=null;    // DisplayPlugin object

    public function setStyle($name)
    {
        $filename=PLUGIN_DIR.DIRECTORY_SEPARATOR.$name.'Display.phk');
        $mnt=require($filename);
        $style=\PHK\Mgr::instance($mnt)->plugin();
        if (!($style instanceof DisplayPlugin)) {
            \PHK\Mgr::umount($mnt);
            throw new Exception($filename.': Invalid plugin');
        }
        $this->style=$style;
    }

    //-- This function displays a string using the current style

    function display($string)
    {
        if (is_null($this->style)) throw new Exception('no defined style');
        $this->style->display($string);
    }

}

:note When creating an instance of the plugin class, the corresponding PHP source is transparently loaded by the autoloader.

The main code could look like this :

$output=new Display();
$output->setStyle('Upper');
...
//-- This will display 'DO YOU HEAR ME ?'

$output->display('Do you hear me ?');

Through this example, you can see how easy it is to implement a plugin mechanism in your software, using the PHK built-in features.

Implementing more complex plugin systems is just an extension of this basic example.

 

Please login or register to add a comment