Plugin architecture

Under construction…

This page will help the development of the new phpPgAdmin Plugin Architecture.

Justificative

Current PPA plugins

PPA has only one plugin: Slony.

Problems:

  • no maintainers
  • deprecated
  • code intrusion

Possible futures new PPA plugins

With a new plugin architecture, more ideas could be developed inside the phpPgAdmin. Below some ideas:

  • Slony current versions (1.2 and 2.0), see http://slony.info
  • port pgpooladmin as plugin
  • Database Designer (Diorman Colmenares 2010 patch)
  • Crud generator (Miguel Ángel Useche Castro)

Development details

Require

A plugin should be able to:

  • add its tree in the browser tree in any level
  • add an entry in the tabs
  • add an entry in the trailer

A plugin must:

  • having dedicated pages, designed in their own folder
  • having their own translation files
  • having their own conf files

PPA plugin structure

  -plugin
  |--conf/
  |  |--config.inc.php
  |--lang/
  |  |--recoded
  |  |  |--english.php
  |  |--english.php
  |  |--Makefile
  |--js/
  |--classes/
  |--images/
  |--help/
  |--tests/ (optional)
  |--themes/ (optional)
  |--ppa_plugin.php

Questions about the structure

  • Does the plugins must have their own tests, themes and libraries directories?
    • ⇒ at least, images. If the plugin rely on some external projects, it might worth putting them in plugins/libraries, so all plugins can share libraries if they use the same
  • What attributes and methods the plugin class need to have?
    • too soon to discuss that

TODO

  • Refactor the Slony plugin code to adapt to the new plugin architecture
  • Refactor the Plugin.php class
  • Create a plugin example
  • Create a documentation that could help the development of new plugins

How the plugin will work on this architecture

Plugin activation

Add in the config.inc.php a new variable $conf['plugins'], this way the PPA will just check which plugins are activated.

Example 1:

/* config.inc.php */
...
$conf['plugins'] = 'ppa_slony, ppa_crud, ppa_another';
...

Example 2:

/* config.inc.php */
...
$conf['plugins'][] = 'ppa_slony';
$conf['plugins'][] = 'ppa_crud';
$conf['plugins'][] = 'ppa_another';
...

Example 3:

/* config.inc.php */
...
$conf['plugins']['ppa_slony'] = true;
$conf['plugins']['ppa_crud'] = true;
$conf['plugins']['ppa_another'] = false;
...

ioguix: all of the above options seems ok to me. Second option sounds good to me.

Plugin execution

ioguix: please, study the design pattern “listener” (sometime called observer). See http://en.wikipedia.org/wiki/Observer_pattern as first pointer. Moreover, it seems there's a “Hook” pattern floating around the web, not sure exactly what are the diff between both of them…

To make it short, these design pattern can probably handle trail/tab/tree and stuffs:

  1. plugins register their functions to the events the want to hook to. this can be done in plugin's constructors, called from lib.inc.php when it instantiate them
  2. when the given code is executed (either the building tree, tab, trail, whatever), it “fire” the even by executing all the functions registred by plugins (before/at/after ?)

Check your reference part, architectures are probably close to this concept. At least, when looking for some pointers about this, I found the drupal one was pretty close to this concept

/ioguix

asleo: yeah, and in the drupal architecture, plugins can integrate with each other.

The activated plugins, will be include in the lib.inc.php file.

Example:

/* lib.inc.php */
...
$obj_plugin_manager = new PluginManager();
//register the plugins and their functions
foreach ($activated_plugins as $plugin) {
  include_once('./plugins/'.$plugin.'/plugin.php');
  
  $obj_plugin = new $plugin($obj_plugin_manager);
  $obj_plugin_manager->add_plugin($obj_plugin);
}
...

/ioguix Nah, disagree with that, core shouldn't look for existing methods etc in plugins. Plugins should register themselves to events they need to mess with.

  1. we need a global “plugin manager” object
  2. loop on activated plugins from lib.inc.php
  3. instantiate each plugin, calling their constructor
  4. from plugins constructor, they register themselves to predefined events calling a method from the “plugin manager” object
  5. as instance, in PPA's code, before/when/after building the trail, we call a “plugin manager” method that will loop on plugin that register to this event and execute the associated method.

It probably needs some more steps, espcialy if we want plugins beeing able to fire new events as well to interact with each others (is it really needed presently ?)… /ioguix

/asleo About the the plugins have interaction with each other, this is not needed presently, but can be done. I change the example code, could you see it please? example code /asleo

/ioguix Sounds good to me :)

There's some cosmetic changes and moving some bits arounds, but nothing really important to mention here. I guess you can start writing a clean proposal. /ioguix

Dealing with trail

The plugin will need to have a method register_trail that will be called when the plugin be started in the lib.inc.php.

...
...
/* Some still undefined file in the ppa_plugin.php */
function register_trail() {
  $array = /* Plugin's trail items */;
}
...
...
...
/* Place when this plugin's function will be registered */
$plugins_trail_functions[] = array('register_trail', $plugin);
...
...
...
/* Place when this plugin's function will be executed, maybe when the PPA shows the trail */
foreach($plugins_trail_functions as $trail_function) {
  /* update the trail, register more items... */
}
...
...

There is an example code that I create to show this logic working.

Dealing with tabs

Dealing with tabs will be similar to dealing with trail.

Dealing with browser tree

Dealing with the browser tree will be similar to dealing with trail and tabs.

Dealing with another thing

Dealing with 'another thing' will be similar to dealing with trail, tabs and the browser tree. In short we will use the 'Hook Pattern' here, so this way, if a plugin X wants to integrate with another one (plugin Y), the plugin Y will need to register the functions of the plugin X, so, after the plugin X be registered by the PPA core.

Questions
  1. How to deal with the browser tree? Note: browser tree's distribuition logic need to be the same of the trails' and tabs'.
    • ⇒ See the above
  2. Could a plugin be showed in differents levels of the browser tree at the same time?
    • ⇒ yes

References

Observer design pattern

Hook design pattern

 
SourceForge
devs/plugin_architecture.txt · Last modified: 2011/03/25 08:46 by ioguix