blob: 470e6a9ee1feb2073329164b0d066991cace9f07 [file] [log] [blame]
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +00001# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
ddkilzer@apple.com57772842014-10-16 16:00:58 +00004#
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +00005# This Source Code Form is "Incompatible With Secondary Licenses", as
6# defined by the Mozilla Public License, v. 2.0.
ddkilzer@apple.com57772842014-10-16 16:00:58 +00007
8# This exists to implement the template-before_process hook.
9package Bugzilla::Template::Context;
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +000010
11use 5.10.1;
ddkilzer@apple.com57772842014-10-16 16:00:58 +000012use strict;
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +000013use warnings;
14
15use parent qw(Template::Context);
ddkilzer@apple.com57772842014-10-16 16:00:58 +000016
17use Bugzilla::Hook;
18use Scalar::Util qw(blessed);
19
20sub process {
21 my $self = shift;
22 # We don't want to run the template_before_process hook for
23 # template hooks (but we do want it to run if a hook calls
24 # PROCESS inside itself). The problem is that the {component}->{name} of
25 # hooks is unreliable--sometimes it starts with ./ and it's the
26 # full path to the hook template, and sometimes it's just the relative
27 # name (like hook/global/field-descs-end.none.tmpl). Also, calling
28 # template_before_process for hook templates doesn't seem too useful,
29 # because that's already part of the extension and they should be able
30 # to modify their hook if they want (or just modify the variables in the
31 # calling template).
32 if (not delete $self->{bz_in_hook}) {
33 $self->{bz_in_process} = 1;
34 }
35 my $result = $self->SUPER::process(@_);
36 delete $self->{bz_in_process};
37 return $result;
38}
39
40# This method is called by Template-Toolkit exactly once per template or
41# block (look at a compiled template) so this is an ideal place for us to
42# modify the variables before a template or block runs.
43#
44# We don't do it during Context::process because at that time
45# our stash hasn't been set correctly--the parameters we were passed
46# in the PROCESS or INCLUDE directive haven't been set, and if we're
47# in an INCLUDE, the stash is not yet localized during process().
48sub stash {
49 my $self = shift;
50 my $stash = $self->SUPER::stash(@_);
51
52 my $name = $stash->{component}->{name};
53 my $pre_process = $self->config->{PRE_PROCESS};
54
55 # Checking bz_in_process tells us that we were indeed called as part of a
56 # Context::process, and not at some other point.
57 #
58 # Checking $name makes sure that we're processing a file, and not just a
59 # block, by checking that the name has a period in it. We don't allow
60 # blocks because their names are too unreliable--an extension could have
61 # a block with the same name, or multiple files could have a same-named
62 # block, and then your extension would malfunction.
63 #
64 # We also make sure that we don't run, ever, during the PRE_PROCESS
65 # templates, because if somebody calls Throw*Error globally inside of
66 # template_before_process, that causes an infinite recursion into
67 # the PRE_PROCESS templates (because Bugzilla, while inside
68 # global/intialize.none.tmpl, loads the template again to create the
69 # template object for Throw*Error).
70 #
71 # Checking Bugzilla::Hook::in prevents infinite recursion on this hook.
72 if ($self->{bz_in_process} and $name =~ /\./
73 and !grep($_ eq $name, @$pre_process)
74 and !Bugzilla::Hook::in('template_before_process'))
75 {
76 Bugzilla::Hook::process("template_before_process",
77 { vars => $stash, context => $self,
78 file => $name });
79 }
80
81 # This prevents other calls to stash() that might somehow happen
82 # later in the file from also triggering the hook.
83 delete $self->{bz_in_process};
84
85 return $stash;
86}
87
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +000088sub filter {
89 my ($self, $name, $args) = @_;
90 # If we pass an alias for the filter name, the filter code is cached
91 # instead of looking for it at each call.
92 # If the filter has arguments, then we can't cache it.
93 $self->SUPER::filter($name, $args, $args ? undef : $name);
94}
95
ddkilzer@apple.com57772842014-10-16 16:00:58 +000096# We need a DESTROY sub for the same reason that Bugzilla::CGI does.
97sub DESTROY {
98 my $self = shift;
99 $self->SUPER::DESTROY(@_);
100};
101
1021;
ddkilzer@apple.com8040bb02017-03-21 16:27:49 +0000103
104=head1 B<Methods in need of POD>
105
106=over
107
108=item stash
109
110=item filter
111
112=item process
113
114=back