1#============================================================= -*-Perl-*- 2# 3# Template::Plugin 4# 5# DESCRIPTION 6# 7# Module defining a base class for a plugin object which can be loaded 8# and instantiated via the USE directive. 9# 10# AUTHOR 11# Andy Wardley <abw@wardley.org> 12# 13# COPYRIGHT 14# Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. 15# 16# This module is free software; you can redistribute it an/or 17# modify it under the same terms as Perl itself. 18# 19#============================================================================ 20 21package Template::Plugin; 22 23use strict; 24use warnings; 25use base 'Template::Base'; 26 27our $VERSION = 2.70; 28our $DEBUG = 0 unless defined $DEBUG; 29our $ERROR = ''; 30our $AUTOLOAD; 31 32 33#======================================================================== 34# ----- CLASS METHODS ----- 35#======================================================================== 36 37#------------------------------------------------------------------------ 38# load() 39# 40# Class method called when the plugin module is first loaded. It 41# returns the name of a class (by default, its own class) or a prototype 42# object which will be used to instantiate new objects. The new() 43# method is then called against the class name (class method) or 44# prototype object (object method) to create a new instances of the 45# object. 46#------------------------------------------------------------------------ 47 48sub load { 49 return $_[0]; 50} 51 52 53#------------------------------------------------------------------------ 54# new($context, $delegate, @params) 55# 56# Object constructor which is called by the Template::Context to 57# instantiate a new Plugin object. This base class constructor is 58# used as a general mechanism to load and delegate to other Perl 59# modules. The context is passed as the first parameter, followed by 60# a reference to a delegate object or the name of the module which 61# should be loaded and instantiated. Any additional parameters passed 62# to the USE directive are forwarded to the new() constructor. 63# 64# A plugin object is returned which has an AUTOLOAD method to delegate 65# requests to the underlying object. 66#------------------------------------------------------------------------ 67 68sub new { 69 my $class = shift; 70 bless { 71 }, $class; 72} 73 74sub old_new { 75 my ($class, $context, $delclass, @params) = @_; 76 my ($delegate, $delmod); 77 78 return $class->error("no context passed to $class constructor\n") 79 unless defined $context; 80 81 if (ref $delclass) { 82 # $delclass contains a reference to a delegate object 83 $delegate = $delclass; 84 } 85 else { 86 # delclass is the name of a module to load and instantiate 87 ($delmod = $delclass) =~ s|::|/|g; 88 89 eval { 90 require "$delmod.pm"; 91 $delegate = $delclass->new(@params) 92 || die "failed to instantiate $delclass object\n"; 93 }; 94 return $class->error($@) if $@; 95 } 96 97 bless { 98 _CONTEXT => $context, 99 _DELEGATE => $delegate, 100 _PARAMS => \@params, 101 }, $class; 102} 103 104 105#------------------------------------------------------------------------ 106# fail($error) 107# 108# Version 1 error reporting function, now replaced by error() inherited 109# from Template::Base. Raises a "deprecated function" warning and then 110# calls error(). 111#------------------------------------------------------------------------ 112 113sub fail { 114 my $class = shift; 115 my ($pkg, $file, $line) = caller(); 116 warn "Template::Plugin::fail() is deprecated at $file line $line. Please use error()\n"; 117 $class->error(@_); 118} 119 120 121#======================================================================== 122# ----- OBJECT METHODS ----- 123#======================================================================== 124 125#------------------------------------------------------------------------ 126# AUTOLOAD 127# 128# General catch-all method which delegates all calls to the _DELEGATE 129# object. 130#------------------------------------------------------------------------ 131 132sub OLD_AUTOLOAD { 133 my $self = shift; 134 my $method = $AUTOLOAD; 135 136 $method =~ s/.*:://; 137 return if $method eq 'DESTROY'; 138 139 if (ref $self eq 'HASH') { 140 my $delegate = $self->{ _DELEGATE } || return; 141 return $delegate->$method(@_); 142 } 143 my ($pkg, $file, $line) = caller(); 144# warn "no such '$method' method called on $self at $file line $line\n"; 145 return undef; 146} 147 148 1491; 150 151__END__ 152 153=head1 NAME 154 155Template::Plugin - Base class for Template Toolkit plugins 156 157=head1 SYNOPSIS 158 159 package MyOrg::Template::Plugin::MyPlugin; 160 use base qw( Template::Plugin ); 161 use Template::Plugin; 162 use MyModule; 163 164 sub new { 165 my $class = shift; 166 my $context = shift; 167 bless { 168 ... 169 }, $class; 170 } 171 172=head1 DESCRIPTION 173 174A "plugin" for the Template Toolkit is simply a Perl module which 175exists in a known package location (e.g. C<Template::Plugin::*>) and 176conforms to a regular standard, allowing it to be loaded and used 177automatically. 178 179The C<Template::Plugin> module defines a base class from which other 180plugin modules can be derived. A plugin does not have to be derived 181from Template::Plugin but should at least conform to its object-oriented 182interface. 183 184It is recommended that you create plugins in your own package namespace 185to avoid conflict with toolkit plugins. e.g. 186 187 package MyOrg::Template::Plugin::FooBar; 188 189Use the L<PLUGIN_BASE|Template::Manual::Config#PLUGIN_BASE> option to specify 190the namespace that you use. e.g. 191 192 use Template; 193 my $template = Template->new({ 194 PLUGIN_BASE => 'MyOrg::Template::Plugin', 195 }); 196 197=head1 METHODS 198 199The following methods form the basic interface between the Template 200Toolkit and plugin modules. 201 202=head2 load($context) 203 204This method is called by the Template Toolkit when the plugin module 205is first loaded. It is called as a package method and thus implicitly 206receives the package name as the first parameter. A reference to the 207L<Template::Context> object loading the plugin is also passed. The 208default behaviour for the C<load()> method is to simply return the class 209name. The calling context then uses this class name to call the C<new()> 210package method. 211 212 package MyPlugin; 213 214 sub load { # called as MyPlugin->load($context) 215 my ($class, $context) = @_; 216 return $class; # returns 'MyPlugin' 217 } 218 219=head2 new($context, @params) 220 221This method is called to instantiate a new plugin object for the C<USE> 222directive. It is called as a package method against the class name returned by 223L<load()>. A reference to the L<Template::Context> object creating the plugin 224is passed, along with any additional parameters specified in the C<USE> 225directive. 226 227 sub new { # called as MyPlugin->new($context) 228 my ($class, $context, @params) = @_; 229 bless { 230 _CONTEXT => $context, 231 }, $class; # returns blessed MyPlugin object 232 } 233 234=head2 error($error) 235 236This method, inherited from the L<Template::Base> module, is used for 237reporting and returning errors. It can be called as a package method 238to set/return the C<$ERROR> package variable, or as an object method to 239set/return the object C<_ERROR> member. When called with an argument, it 240sets the relevant variable and returns C<undef.> When called without an 241argument, it returns the value of the variable. 242 243 package MyPlugin; 244 use base 'Template::Plugin'; 245 246 sub new { 247 my ($class, $context, $dsn) = @_; 248 249 return $class->error('No data source specified') 250 unless $dsn; 251 252 bless { 253 _DSN => $dsn, 254 }, $class; 255 } 256 257 package main; 258 259 my $something = MyPlugin->new() 260 || die MyPlugin->error(), "\n"; 261 262 $something->do_something() 263 || die $something->error(), "\n"; 264 265=head1 DEEPER MAGIC 266 267The L<Template::Context> object that handles the loading and use of plugins 268calls the L<new()> and L<error()> methods against the package name returned by 269the L<load()> method. In pseudo-code terms looks something like this: 270 271 $class = MyPlugin->load($context); # returns 'MyPlugin' 272 273 $object = $class->new($context, @params) # MyPlugin->new(...) 274 || die $class->error(); # MyPlugin->error() 275 276The L<load()> method may alterately return a blessed reference to an 277object instance. In this case, L<new()> and L<error()> are then called as 278I<object> methods against that prototype instance. 279 280 package YourPlugin; 281 282 sub load { 283 my ($class, $context) = @_; 284 bless { 285 _CONTEXT => $context, 286 }, $class; 287 } 288 289 sub new { 290 my ($self, $context, @params) = @_; 291 return $self; 292 } 293 294In this example, we have implemented a 'Singleton' plugin. One object 295gets created when L<load()> is called and this simply returns itself for 296each call to L<new().> 297 298Another implementation might require individual objects to be created 299for every call to L<new(),> but with each object sharing a reference to 300some other object to maintain cached data, database handles, etc. 301This pseudo-code example demonstrates the principle. 302 303 package MyServer; 304 305 sub load { 306 my ($class, $context) = @_; 307 bless { 308 _CONTEXT => $context, 309 _CACHE => { }, 310 }, $class; 311 } 312 313 sub new { 314 my ($self, $context, @params) = @_; 315 MyClient->new($self, @params); 316 } 317 318 sub add_to_cache { ... } 319 320 sub get_from_cache { ... } 321 322 package MyClient; 323 324 sub new { 325 my ($class, $server, $blah) = @_; 326 bless { 327 _SERVER => $server, 328 _BLAH => $blah, 329 }, $class; 330 } 331 332 sub get { 333 my $self = shift; 334 $self->{ _SERVER }->get_from_cache(@_); 335 } 336 337 sub put { 338 my $self = shift; 339 $self->{ _SERVER }->add_to_cache(@_); 340 } 341 342When the plugin is loaded, a C<MyServer> instance is created. The L<new()> 343method is called against this object which instantiates and returns a C<MyClient> 344object, primed to communicate with the creating C<MyServer>. 345 346=head1 AUTHOR 347 348Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/> 349 350=head1 COPYRIGHT 351 352Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. 353 354This module is free software; you can redistribute it and/or 355modify it under the same terms as Perl itself. 356 357=head1 SEE ALSO 358 359L<Template>, L<Template::Plugins>, L<Template::Context> 360 361=cut 362 363# Local Variables: 364# mode: perl 365# perl-indent-level: 4 366# indent-tabs-mode: nil 367# End: 368# 369# vim: expandtab shiftwidth=4: 370