1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
{
my $self = shift;
my $app = MT->instance;
=item
### SUMMARY
My plugin-created MT::App::CMS subclass requires the use of the
Transformer callbacks in order to modify the left nav of the system
menu and they work perfectly well for any mode served by MT::App::CMS.
However, any modes served by my plugin app do not exhibit the
Transformations.
Why? Because plugin modes are generated using the load_tmpl method in
MT::Plugin which, for some reason, lacks the Transformer callbacks found
in MT::App::load_tmpl. (Actually, I am guessing the reason is because
most plugins bootstrap their own apps instead of subclassing an MT::App
and masquerading as that app, adding methods and using the apps
templates.)
Unfortunately, plugins can not easily use MT::App::load_tmpl because that
function doesn't register the tmpl directory in the plugin envelope like
MT::Plugin's version. What's more, there's no way to pass in a paramter
to MT::App::load_tmpl to add the directory to the search path.
### QUESTIONS
* Why doesn't MT::Plugin->load_tmpl allow for Transformer callbacks
when my plugin is an MT::App::CMS subclass?
* Why doesn't MT::App->load_tmpl allow prepending of tmpl paths onto
its search array?
### MAKING MT::App::load_tmpl FIND THE PLUGIN'S TMPL DIRECTORY
So I found an awesome hack in the HTML::Template POD docs to take care
of the problem of MT::App::load_tmpl not finding the plugin tmpl
directory: the HTML_TEMPLATE_ROOT environment variable.
The value of HTML_TEMPLATE_ROOT is recognized by HTML::Template's
internal methods and **prepended to the search paths array** giving it
priority over the MT::App::CMS templates in the fallback order.
my $tmpl;
{
local $ENV{HTML_TEMPLATE_ROOT} =
File::Spec->catdir($app->mt_dir,
$plugin->envelope,
'tmpl');
$tmpl = $app->load_tmpl(@_);
}
Benefits:
* Can be lexically scoped so as not to interfere with the template
loading of identically named templates by other plugins or the app
itself.
* No code hacking necessary
* Native, documented functionality of HTML::Template
Problems:
* In some environments, this variable may not be settable or may be
purposefully set to another value.
* The default template parameters in MT::App are specific to the
MT::App's and often less correct than those in MT::Plugin, even
when the plugin app is a subclass of MT::App::CMS.
### ENABLING TRANSFORMER CALLBACKS IN MT::Plugin
After staring at the code long enough, I saw that it was actually quite
simple to enable the Transformer callbacks in plugin-created modes with
templates loaded by MT::Plugin::load_tmpl.
To do so, you simply add the same filter param that can be found in
MT::App::load_tmpl to the load_tmpl arguments, like so:
=cut
push(@_, filter => sub {
my $fname = $HTML::Template::this_file;
if ($fname) {
$fname = File::Basename::basename($fname);
$fname =~ s/\.tmpl$//;
$app->run_callbacks(ref($app) . "::AppTemplateSource.$fname",
$app, $_[0]);
} else {
$app->run_callbacks(ref($app)."::AppTemplateSource",
$app, $_[0]);
}
$_[0];
});
# At this point, we can now call MT::Plugin (the superclass) and
# have our callback triggered.
my $tmpl = $self->SUPER::load_tmpl(@_);
=item
Benefits:
* Uses MT's own functions and should be consistent in all environments
* Could be switched on and off on a per page basis if you liked
* Plugin now inherits all of MT::Plugin's default template params
Problems:
* Can't see any at the moment.
=cut
# Add any parameters necessary for this plugin. e.g.
# $tmpl->param(add_showhidejs => 1) if $MT::VERSION == '3.2';
$tmpl;
}
|
