ok
Direktori : /usr/local/lib64/perl5/Template/ |
Current File : //usr/local/lib64/perl5/Template/Plugin.pm |
#============================================================= -*-Perl-*- # # Template::Plugin # # DESCRIPTION # # Module defining a base class for a plugin object which can be loaded # and instantiated via the USE directive. # # AUTHOR # Andy Wardley <abw@wardley.org> # # COPYRIGHT # Copyright (C) 1996-2022 Andy Wardley. All Rights Reserved. # # This module is free software; you can redistribute it an/or # modify it under the same terms as Perl itself. # #============================================================================ package Template::Plugin; use strict; use warnings; use base 'Template::Base'; our $VERSION = '3.100'; our $DEBUG = 0 unless defined $DEBUG; our $ERROR = ''; our $AUTOLOAD; #======================================================================== # ----- CLASS METHODS ----- #======================================================================== #------------------------------------------------------------------------ # load() # # Class method called when the plugin module is first loaded. It # returns the name of a class (by default, its own class) or a prototype # object which will be used to instantiate new objects. The new() # method is then called against the class name (class method) or # prototype object (object method) to create a new instances of the # object. #------------------------------------------------------------------------ sub load { return $_[0]; } #------------------------------------------------------------------------ # new($context, $delegate, @params) # # Object constructor which is called by the Template::Context to # instantiate a new Plugin object. This base class constructor is # used as a general mechanism to load and delegate to other Perl # modules. The context is passed as the first parameter, followed by # a reference to a delegate object or the name of the module which # should be loaded and instantiated. Any additional parameters passed # to the USE directive are forwarded to the new() constructor. # # A plugin object is returned which has an AUTOLOAD method to delegate # requests to the underlying object. #------------------------------------------------------------------------ sub new { my $class = shift; bless { }, $class; } #------------------------------------------------------------------------ # fail($error) # # Version 1 error reporting function, now replaced by error() inherited # from Template::Base. Raises a "deprecated function" warning and then # calls error(). #------------------------------------------------------------------------ sub fail { my $class = shift; my ($pkg, $file, $line) = caller(); warn "Template::Plugin::fail() is deprecated at $file line $line. Please use error()\n"; $class->error(@_); } 1; __END__ =head1 NAME Template::Plugin - Base class for Template Toolkit plugins =head1 SYNOPSIS package MyOrg::Template::Plugin::MyPlugin; use base qw( Template::Plugin ); use Template::Plugin; use MyModule; sub new { my $class = shift; my $context = shift; bless { ... }, $class; } =head1 DESCRIPTION A "plugin" for the Template Toolkit is simply a Perl module which exists in a known package location (e.g. C<Template::Plugin::*>) and conforms to a regular standard, allowing it to be loaded and used automatically. The C<Template::Plugin> module defines a base class from which other plugin modules can be derived. A plugin does not have to be derived from Template::Plugin but should at least conform to its object-oriented interface. It is recommended that you create plugins in your own package namespace to avoid conflict with toolkit plugins. e.g. package MyOrg::Template::Plugin::FooBar; Use the L<PLUGIN_BASE|Template::Manual::Config#PLUGIN_BASE> option to specify the namespace that you use. e.g. use Template; my $template = Template->new({ PLUGIN_BASE => 'MyOrg::Template::Plugin', }); =head1 METHODS The following methods form the basic interface between the Template Toolkit and plugin modules. =head2 load($context) This method is called by the Template Toolkit when the plugin module is first loaded. It is called as a package method and thus implicitly receives the package name as the first parameter. A reference to the L<Template::Context> object loading the plugin is also passed. The default behaviour for the C<load()> method is to simply return the class name. The calling context then uses this class name to call the C<new()> package method. package MyPlugin; sub load { # called as MyPlugin->load($context) my ($class, $context) = @_; return $class; # returns 'MyPlugin' } =head2 new($context, @params) This method is called to instantiate a new plugin object for the C<USE> directive. It is called as a package method against the class name returned by L<load()>. A reference to the L<Template::Context> object creating the plugin is passed, along with any additional parameters specified in the C<USE> directive. sub new { # called as MyPlugin->new($context) my ($class, $context, @params) = @_; bless { _CONTEXT => $context, }, $class; # returns blessed MyPlugin object } =head2 error($error) This method, inherited from the L<Template::Base> module, is used for reporting and returning errors. It can be called as a package method to set/return the C<$ERROR> package variable, or as an object method to set/return the object C<_ERROR> member. When called with an argument, it sets the relevant variable and returns C<undef.> When called without an argument, it returns the value of the variable. package MyPlugin; use base 'Template::Plugin'; sub new { my ($class, $context, $dsn) = @_; return $class->error('No data source specified') unless $dsn; bless { _DSN => $dsn, }, $class; } package main; my $something = MyPlugin->new() || die MyPlugin->error(), "\n"; $something->do_something() || die $something->error(), "\n"; =head1 DEEPER MAGIC The L<Template::Context> object that handles the loading and use of plugins calls the L<new()> and L<error()> methods against the package name returned by the L<load()> method. In pseudo-code terms looks something like this: $class = MyPlugin->load($context); # returns 'MyPlugin' $object = $class->new($context, @params) # MyPlugin->new(...) || die $class->error(); # MyPlugin->error() The L<load()> method may alternately return a blessed reference to an object instance. In this case, L<new()> and L<error()> are then called as I<object> methods against that prototype instance. package YourPlugin; sub load { my ($class, $context) = @_; bless { _CONTEXT => $context, }, $class; } sub new { my ($self, $context, @params) = @_; return $self; } In this example, we have implemented a 'Singleton' plugin. One object gets created when L<load()> is called and this simply returns itself for each call to L<new().> Another implementation might require individual objects to be created for every call to L<new(),> but with each object sharing a reference to some other object to maintain cached data, database handles, etc. This pseudo-code example demonstrates the principle. package MyServer; sub load { my ($class, $context) = @_; bless { _CONTEXT => $context, _CACHE => { }, }, $class; } sub new { my ($self, $context, @params) = @_; MyClient->new($self, @params); } sub add_to_cache { ... } sub get_from_cache { ... } package MyClient; sub new { my ($class, $server, $blah) = @_; bless { _SERVER => $server, _BLAH => $blah, }, $class; } sub get { my $self = shift; $self->{ _SERVER }->get_from_cache(@_); } sub put { my $self = shift; $self->{ _SERVER }->add_to_cache(@_); } When the plugin is loaded, a C<MyServer> instance is created. The L<new()> method is called against this object which instantiates and returns a C<MyClient> object, primed to communicate with the creating C<MyServer>. =head1 AUTHOR Andy Wardley E<lt>abw@wardley.orgE<gt> L<http://wardley.org/> =head1 COPYRIGHT Copyright (C) 1996-2022 Andy Wardley. All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L<Template>, L<Template::Plugins>, L<Template::Context> =cut # Local Variables: # mode: perl # perl-indent-level: 4 # indent-tabs-mode: nil # End: # # vim: expandtab shiftwidth=4: