rainphp/raintpl3 — pull request #19 by rumman23 (2012-04-04 07:38:33+00:00)
Title: Plugins as classes

Hi,
here's the code that resulted from discussion on raintpl forum (http://www.raintpl.com/Forum/Development-Forum/Rain-TPL-3/?t=157).

There is also described how it works, so I will not repeat it here in detail, I will just add a small intro for plugin developers that you can add later to the doc (after you translate it to proper english).

Commits add plugin container that calls hooks on registrated plugins, plugin interface to ensure that plugin has desired api and base implementation of plugin. I rewrote the path replace plugin to a class based plugin.

Tpl class has new static property with reference to plugin container (I'm not happy with static properties, because they have some drawbacks of global variables, but this can be part of another improvement :))

All new classes follow the PSR-0 convention (as discussed in thread) and are included in main tpl file. This is ok for such small project.

Rain directory MUST now be in some folder defined in include paths. So before it can be used users have to set include path to their library folders (I gues the majority have this anyway):

set_include_path('/path/to/library' . PATH_SEPARATOR . get_include_path());
require_once('Rain/Tpl.php');
// configure and use as usual....
\Rain\Tpl::configure();

Classes are namespaced, because I saw you use namespace in main file. You can refactor this to common underscore notation in case you want to support php 5.2 and lower

I have added some unit tests to check that plugin api works. You can delete this if you do not use it (However I think each public project should have some automated testing to check that api is not broken with new features)

----- Plugins

Rain Tpl can be enhanced with plugins. Each plugin can register its methods to one or more extension points that are integrated in template engine. As a template is processed and extension point is reached all registrated hooks are notified.

Hook methods are invoked with context object. This is simple crate that contains items depending on hook name. Context object always contains '_hook_name' key with name of extension point. Plugin is free to modify context object items (hook into rain tpl) or add they own items (communicate with other plugins).
The context object is new for each processed template.

Plugins are registered statically - one plugin instance will work with all templates processed by all Rain Tpl instances.

Example:

// Define plugin that will wrap each template with additional div after it is parsed
class Wrapper extends \Rain\Tpl\Plugin {
protected $hooks = array('after_parse');
private $style = '1px solid black';

public function after_parse($context) {
$context->code = '

' . $context->template_filepath . '' . $context->code . '

';
}
public function set_style($style) { $this->style = $style; }
}

// use wrapper plugin to mark all used templates on devel
if ('devel' === APP_ENV && $_GET['tempalteinfo']) {
Rain\Tpl::register_plugin(new Wrapper(array('style' => '2px solid red;'));
}