| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this |
| # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| # |
| # This Source Code Form is "Incompatible With Secondary Licenses", as |
| # defined by the Mozilla Public License, v. 2.0. |
| |
| # This exists to implement the template-before_process hook. |
| package Bugzilla::Template::Context; |
| |
| use 5.10.1; |
| use strict; |
| use warnings; |
| |
| use parent qw(Template::Context); |
| |
| use Bugzilla::Hook; |
| use Scalar::Util qw(blessed); |
| |
| sub process { |
| my $self = shift; |
| # We don't want to run the template_before_process hook for |
| # template hooks (but we do want it to run if a hook calls |
| # PROCESS inside itself). The problem is that the {component}->{name} of |
| # hooks is unreliable--sometimes it starts with ./ and it's the |
| # full path to the hook template, and sometimes it's just the relative |
| # name (like hook/global/field-descs-end.none.tmpl). Also, calling |
| # template_before_process for hook templates doesn't seem too useful, |
| # because that's already part of the extension and they should be able |
| # to modify their hook if they want (or just modify the variables in the |
| # calling template). |
| if (not delete $self->{bz_in_hook}) { |
| $self->{bz_in_process} = 1; |
| } |
| my $result = $self->SUPER::process(@_); |
| delete $self->{bz_in_process}; |
| return $result; |
| } |
| |
| # This method is called by Template-Toolkit exactly once per template or |
| # block (look at a compiled template) so this is an ideal place for us to |
| # modify the variables before a template or block runs. |
| # |
| # We don't do it during Context::process because at that time |
| # our stash hasn't been set correctly--the parameters we were passed |
| # in the PROCESS or INCLUDE directive haven't been set, and if we're |
| # in an INCLUDE, the stash is not yet localized during process(). |
| sub stash { |
| my $self = shift; |
| my $stash = $self->SUPER::stash(@_); |
| |
| my $name = $stash->{component}->{name}; |
| my $pre_process = $self->config->{PRE_PROCESS}; |
| |
| # Checking bz_in_process tells us that we were indeed called as part of a |
| # Context::process, and not at some other point. |
| # |
| # Checking $name makes sure that we're processing a file, and not just a |
| # block, by checking that the name has a period in it. We don't allow |
| # blocks because their names are too unreliable--an extension could have |
| # a block with the same name, or multiple files could have a same-named |
| # block, and then your extension would malfunction. |
| # |
| # We also make sure that we don't run, ever, during the PRE_PROCESS |
| # templates, because if somebody calls Throw*Error globally inside of |
| # template_before_process, that causes an infinite recursion into |
| # the PRE_PROCESS templates (because Bugzilla, while inside |
| # global/intialize.none.tmpl, loads the template again to create the |
| # template object for Throw*Error). |
| # |
| # Checking Bugzilla::Hook::in prevents infinite recursion on this hook. |
| if ($self->{bz_in_process} and $name =~ /\./ |
| and !grep($_ eq $name, @$pre_process) |
| and !Bugzilla::Hook::in('template_before_process')) |
| { |
| Bugzilla::Hook::process("template_before_process", |
| { vars => $stash, context => $self, |
| file => $name }); |
| } |
| |
| # This prevents other calls to stash() that might somehow happen |
| # later in the file from also triggering the hook. |
| delete $self->{bz_in_process}; |
| |
| return $stash; |
| } |
| |
| sub filter { |
| my ($self, $name, $args) = @_; |
| # If we pass an alias for the filter name, the filter code is cached |
| # instead of looking for it at each call. |
| # If the filter has arguments, then we can't cache it. |
| $self->SUPER::filter($name, $args, $args ? undef : $name); |
| } |
| |
| # We need a DESTROY sub for the same reason that Bugzilla::CGI does. |
| sub DESTROY { |
| my $self = shift; |
| $self->SUPER::DESTROY(@_); |
| }; |
| |
| 1; |
| |
| =head1 B<Methods in need of POD> |
| |
| =over |
| |
| =item stash |
| |
| =item filter |
| |
| =item process |
| |
| =back |