\chapter{Plugins}
\label{chap:plugins}

Gantry is extensible in many ways.  Most of the time it is enough to just
use regular modules in the regular way.  But there are times when a bit
more is required for proper function.  This chapter explains how we
implement plugins which change -- or more likely, augment -- the behavior
of Gantry site objects.

Most plugins alter the behavior of Gantry site objects by mixing in
methods.  This is easy to do.

To have an example, suppose that a database we don't control gives us
data in feet, but we need to show it to our customer in meters.  To make
it easy to access this method in controller methods, we want the syntax
to be like this:

\begin{verbatim}
    my $meters = $self->ft2m( $feet_from_database );
\end{verbatim}

But, we only want \verb+ft2m+ to be available, we don't want it by default.
That rules out putting into Gantry.pm.  Further, while we could put it in
our app's main module, that wouldn't help us if a different app needs the
same conversion.  So, let's make a plugin:

\begin{verbatim}
package Gantry::Plugins::UnitConvert
use strict;

use Exporter;
our @EXPORT = qw( ft2m );

sub ft2m {
    my $self = shift;
    my $feet = shift;

    return $feet * .3048;
}
\end{verbatim}

The key is to write a method (which expects a Gantry site object as its
invocant) and export it -- or mix it -- into the caller's namespace.
Users then have an array of choices for how to use this plugin.

They could include it in the same use statement where they choose an Engine:

\begin{verbatim}
    use GantryBased::App qw( -Engine=MP13 -TemplateEngine=TT UnitConvert );
\end{verbatim}

But that puts it in all the modules of the whole app.  Likely, it will make
more sense to use it more sparingly, in the modules which actually need it.
So, it should probably go near the top of the module that needs it:

\begin{verbatim}
package GantryBased::App::Dist
use strict;
#...
use Gantry::Plugins::UnitConvert qw( ft2m );
\end{verbatim}

Note that the user does not have to mention the \verb+ft2m+ method by name,
but it will help future readers who wonder where that method came from.
You could also choose to have your plugin export only upon request, by
changing from \verb+@EXPORT+ to \verb+@EXPORT_OK+.  That seems a bit
strange for most plugins, since their whole purpose in life is to inject
their methods into your namespace, but some people may prefer it.  It does
force users to ask for the methods.  That's good documentation.  It also
makes more sense if there are more methods in the plugin, only some
of which make sense together.

Gantry's plugins are generally mixins -- they export methods into their
user's namespace.  This is a powerful way to share code across apps without
worrying about inheritence.  If you stick to explicit imports, it is still
fairly easy to track down the origin of the code.

The only plugin that doesn't export is Gantry::Plugins::CRUD which has
an object oriented approach.  It is in the Plugins namespace due to its
similarity with Gantry::Plugins::AutoCRUD which does export a number of
methods.
