| Filename | /usr/lib/perl5/Template/Context.pm |
| Statements | Executed 2760 statements in 10.5ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 214 | 15 | 4 | 3.64ms | 6.44ms | Template::Context::filter |
| 9 | 2 | 2 | 1.64ms | 365ms | Template::Context::process (recurses: max depth 1, inclusive time 343ms) |
| 10 | 2 | 2 | 472µs | 776ms | Template::Context::template |
| 1 | 1 | 1 | 124µs | 18.3ms | Template::Context::_init |
| 9 | 1 | 1 | 115µs | 115µs | Template::Context::visit |
| 1 | 1 | 1 | 86µs | 92µs | Template::Context::delocalise |
| 8 | 7 | 1 | 79µs | 343ms | Template::Context::include |
| 1 | 1 | 1 | 66µs | 67µs | Template::Context::BEGIN@30 |
| 9 | 1 | 1 | 47µs | 47µs | Template::Context::leave |
| 1 | 1 | 1 | 39µs | 301µs | Template::Context::localise |
| 9 | 8 | 8 | 38µs | 38µs | Template::Context::stash |
| 1 | 1 | 1 | 27µs | 35µs | Template::Context::BEGIN@23 |
| 1 | 1 | 1 | 23µs | 169µs | Template::Context::BEGIN@33 |
| 9 | 1 | 1 | 22µs | 22µs | Template::Context::CORE:subst (opcode) |
| 1 | 1 | 1 | 21µs | 64µs | Template::Context::BEGIN@29 |
| 1 | 1 | 1 | 20µs | 24µs | Template::Context::BEGIN@27 |
| 1 | 1 | 1 | 20µs | 76µs | Template::Context::BEGIN@31 |
| 1 | 1 | 1 | 18µs | 60µs | Template::Context::BEGIN@34 |
| 1 | 1 | 1 | 16µs | 43µs | Template::Context::BEGIN@24 |
| 1 | 1 | 1 | 15µs | 17µs | Template::Context::BEGIN@28 |
| 1 | 1 | 1 | 15µs | 15µs | Template::Context::DESTROY |
| 1 | 1 | 1 | 14µs | 14µs | Template::Context::reset |
| 1 | 1 | 1 | 13µs | 99µs | Template::Context::BEGIN@25 |
| 1 | 1 | 1 | 9µs | 44µs | Template::Context::BEGIN@35 |
| 0 | 0 | 0 | 0s | 0s | Template::Context::AUTOLOAD |
| 0 | 0 | 0 | 0s | 0s | Template::Context::_dump |
| 0 | 0 | 0 | 0s | 0s | Template::Context::catch |
| 0 | 0 | 0 | 0s | 0s | Template::Context::debugging |
| 0 | 0 | 0 | 0s | 0s | Template::Context::define_block |
| 0 | 0 | 0 | 0s | 0s | Template::Context::define_filter |
| 0 | 0 | 0 | 0s | 0s | Template::Context::define_view |
| 0 | 0 | 0 | 0s | 0s | Template::Context::define_views |
| 0 | 0 | 0 | 0s | 0s | Template::Context::define_vmethod |
| 0 | 0 | 0 | 0s | 0s | Template::Context::insert |
| 0 | 0 | 0 | 0s | 0s | Template::Context::plugin |
| 0 | 0 | 0 | 0s | 0s | Template::Context::throw |
| 0 | 0 | 0 | 0s | 0s | Template::Context::view |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | #============================================================= -*-Perl-*- | ||||
| 2 | # | ||||
| 3 | # Template::Context | ||||
| 4 | # | ||||
| 5 | # DESCRIPTION | ||||
| 6 | # Module defining a context in which a template document is processed. | ||||
| 7 | # This is the runtime processing interface through which templates | ||||
| 8 | # can access the functionality of the Template Toolkit. | ||||
| 9 | # | ||||
| 10 | # AUTHOR | ||||
| 11 | # Andy Wardley <abw@wardley.org> | ||||
| 12 | # | ||||
| 13 | # COPYRIGHT | ||||
| 14 | # Copyright (C) 1996-2007 Andy Wardley. All Rights Reserved. | ||||
| 15 | # | ||||
| 16 | # This module is free software; you can redistribute it and/or | ||||
| 17 | # modify it under the same terms as Perl itself. | ||||
| 18 | # | ||||
| 19 | #============================================================================ | ||||
| 20 | |||||
| 21 | package Template::Context; | ||||
| 22 | |||||
| 23 | 3 | 37µs | 2 | 42µs | # spent 35µs (27+8) within Template::Context::BEGIN@23 which was called:
# once (27µs+8µs) by Template::Config::load at line 23 # spent 35µs making 1 call to Template::Context::BEGIN@23
# spent 8µs making 1 call to strict::import |
| 24 | 3 | 37µs | 2 | 70µs | # spent 43µs (16+27) within Template::Context::BEGIN@24 which was called:
# once (16µs+27µs) by Template::Config::load at line 24 # spent 43µs making 1 call to Template::Context::BEGIN@24
# spent 27µs making 1 call to warnings::import |
| 25 | 3 | 45µs | 2 | 186µs | # spent 99µs (13+86) within Template::Context::BEGIN@25 which was called:
# once (13µs+86µs) by Template::Config::load at line 25 # spent 99µs making 1 call to Template::Context::BEGIN@25
# spent 86µs making 1 call to base::import |
| 26 | |||||
| 27 | 3 | 34µs | 2 | 28µs | # spent 24µs (20+4) within Template::Context::BEGIN@27 which was called:
# once (20µs+4µs) by Template::Config::load at line 27 # spent 24µs making 1 call to Template::Context::BEGIN@27
# spent 4µs making 1 call to UNIVERSAL::import |
| 28 | 3 | 29µs | 2 | 19µs | # spent 17µs (15+2) within Template::Context::BEGIN@28 which was called:
# once (15µs+2µs) by Template::Config::load at line 28 # spent 17µs making 1 call to Template::Context::BEGIN@28
# spent 2µs making 1 call to UNIVERSAL::import |
| 29 | 3 | 40µs | 2 | 106µs | # spent 64µs (21+43) within Template::Context::BEGIN@29 which was called:
# once (21µs+43µs) by Template::Config::load at line 29 # spent 64µs making 1 call to Template::Context::BEGIN@29
# spent 43µs making 1 call to Exporter::import |
| 30 | 3 | 43µs | 2 | 69µs | # spent 67µs (66+2) within Template::Context::BEGIN@30 which was called:
# once (66µs+2µs) by Template::Config::load at line 30 # spent 67µs making 1 call to Template::Context::BEGIN@30
# spent 2µs making 1 call to UNIVERSAL::import |
| 31 | 3 | 48µs | 2 | 132µs | # spent 76µs (20+56) within Template::Context::BEGIN@31 which was called:
# once (20µs+56µs) by Template::Config::load at line 31 # spent 76µs making 1 call to Template::Context::BEGIN@31
# spent 56µs making 1 call to Exporter::import |
| 32 | |||||
| 33 | 3 | 72µs | 2 | 315µs | # spent 169µs (23+146) within Template::Context::BEGIN@33 which was called:
# once (23µs+146µs) by Template::Config::load at line 33 # spent 169µs making 1 call to Template::Context::BEGIN@33
# spent 146µs making 1 call to constant::import |
| 34 | 3 | 38µs | 2 | 102µs | # spent 60µs (18+42) within Template::Context::BEGIN@34 which was called:
# once (18µs+42µs) by Template::Config::load at line 34 # spent 60µs making 1 call to Template::Context::BEGIN@34
# spent 42µs making 1 call to constant::import |
| 35 | 3 | 3.70ms | 2 | 80µs | # spent 44µs (9+35) within Template::Context::BEGIN@35 which was called:
# once (9µs+35µs) by Template::Config::load at line 35 # spent 44µs making 1 call to Template::Context::BEGIN@35
# spent 35µs making 1 call to constant::import |
| 36 | |||||
| 37 | 1 | 1µs | our $VERSION = 2.98; | ||
| 38 | 1 | 1µs | our $DEBUG = 0 unless defined $DEBUG; | ||
| 39 | 1 | 1µs | our $DEBUG_FORMAT = "\n## \$file line \$line : [% \$text %] ##\n"; | ||
| 40 | 1 | 500ns | our $VIEW_CLASS = 'Template::View'; | ||
| 41 | 1 | 200ns | our $AUTOLOAD; | ||
| 42 | |||||
| 43 | #======================================================================== | ||||
| 44 | # ----- PUBLIC METHODS ----- | ||||
| 45 | #======================================================================== | ||||
| 46 | |||||
| 47 | #------------------------------------------------------------------------ | ||||
| 48 | # template($name) | ||||
| 49 | # | ||||
| 50 | # General purpose method to fetch a template and return it in compiled | ||||
| 51 | # form. In the usual case, the $name parameter will be a simple string | ||||
| 52 | # containing the name of a template (e.g. 'header'). It may also be | ||||
| 53 | # a reference to Template::Document object (or sub-class) or a Perl | ||||
| 54 | # sub-routine. These are considered to be compiled templates and are | ||||
| 55 | # returned intact. Finally, it may be a reference to any other kind | ||||
| 56 | # of valid input source accepted by Template::Provider (e.g. scalar | ||||
| 57 | # ref, glob, IO handle, etc). | ||||
| 58 | # | ||||
| 59 | # Templates may be cached at one of 3 different levels. The internal | ||||
| 60 | # BLOCKS member is a local cache which holds references to all | ||||
| 61 | # template blocks used or imported via PROCESS since the context's | ||||
| 62 | # reset() method was last called. This is checked first and if the | ||||
| 63 | # template is not found, the method then walks down the BLOCKSTACK | ||||
| 64 | # list. This contains references to the block definition tables in | ||||
| 65 | # any enclosing Template::Documents that we're visiting (e.g. we've | ||||
| 66 | # been called via an INCLUDE and we want to access a BLOCK defined in | ||||
| 67 | # the template that INCLUDE'd us). If nothing is defined, then we | ||||
| 68 | # iterate through the LOAD_TEMPLATES providers list as a 'chain of | ||||
| 69 | # responsibility' (see Design Patterns) asking each object to fetch() | ||||
| 70 | # the template if it can. | ||||
| 71 | # | ||||
| 72 | # Returns the compiled template. On error, undef is returned and | ||||
| 73 | # the internal ERROR value (read via error()) is set to contain an | ||||
| 74 | # error message of the form "$name: $error". | ||||
| 75 | #------------------------------------------------------------------------ | ||||
| 76 | |||||
| 77 | # spent 776ms (472µs+776) within Template::Context::template which was called 10 times, avg 77.6ms/call:
# 9 times (377µs+311ms) by Template::Context::process at line 309, avg 34.6ms/call
# once (95µs+464ms) by Template::Service::process at line 68 of Template/Service.pm | ||||
| 78 | 202 | 519µs | my ($self, $name) = @_; | ||
| 79 | my ($prefix, $blocks, $defblocks, $provider, $template, $error); | ||||
| 80 | my ($shortname, $blockname, $providers); | ||||
| 81 | |||||
| 82 | $self->debug("template($name)") if $self->{ DEBUG }; | ||||
| 83 | |||||
| 84 | # references to Template::Document (or sub-class) objects objects, or | ||||
| 85 | # CODE references are assumed to be pre-compiled templates and are | ||||
| 86 | # returned intact | ||||
| 87 | 11 | 53µs | return $name # spent 50µs making 10 calls to Scalar::Util::blessed, avg 5µs/call
# spent 3µs making 1 call to UNIVERSAL::isa | ||
| 88 | if (blessed($name) && $name->isa(DOCUMENT)) | ||||
| 89 | || ref($name) eq 'CODE'; | ||||
| 90 | |||||
| 91 | $shortname = $name; | ||||
| 92 | |||||
| 93 | unless (ref $name) { | ||||
| 94 | |||||
| 95 | $self->debug("looking for block [$name]") if $self->{ DEBUG }; | ||||
| 96 | |||||
| 97 | # we first look in the BLOCKS hash for a BLOCK that may have | ||||
| 98 | # been imported from a template (via PROCESS) | ||||
| 99 | return $template | ||||
| 100 | if ($template = $self->{ BLOCKS }->{ $name }); | ||||
| 101 | |||||
| 102 | # then we iterate through the BLKSTACK list to see if any of the | ||||
| 103 | # Template::Documents we're visiting define this BLOCK | ||||
| 104 | foreach $blocks (@{ $self->{ BLKSTACK } }) { | ||||
| 105 | return $template | ||||
| 106 | if $blocks && ($template = $blocks->{ $name }); | ||||
| 107 | } | ||||
| 108 | |||||
| 109 | # now it's time to ask the providers, so we look to see if any | ||||
| 110 | # prefix is specified to indicate the desired provider set. | ||||
| 111 | if ($^O eq 'MSWin32') { | ||||
| 112 | # let C:/foo through | ||||
| 113 | $prefix = $1 if $shortname =~ s/^(\w{2,})://o; | ||||
| 114 | } | ||||
| 115 | else { | ||||
| 116 | 9 | 22µs | $prefix = $1 if $shortname =~ s/^(\w+)://; # spent 22µs making 9 calls to Template::Context::CORE:subst, avg 2µs/call | ||
| 117 | } | ||||
| 118 | |||||
| 119 | if (defined $prefix) { | ||||
| 120 | $providers = $self->{ PREFIX_MAP }->{ $prefix } | ||||
| 121 | || return $self->throw( Template::Constants::ERROR_FILE, | ||||
| 122 | "no providers for template prefix '$prefix'"); | ||||
| 123 | } | ||||
| 124 | } | ||||
| 125 | $providers = $self->{ PREFIX_MAP }->{ default } | ||||
| 126 | || $self->{ LOAD_TEMPLATES } | ||||
| 127 | unless $providers; | ||||
| 128 | |||||
| 129 | |||||
| 130 | # Finally we try the regular template providers which will | ||||
| 131 | # handle references to files, text, etc., as well as templates | ||||
| 132 | # reference by name. If | ||||
| 133 | |||||
| 134 | $blockname = ''; | ||||
| 135 | while ($shortname) { | ||||
| 136 | $self->debug("asking providers for [$shortname] [$blockname]") | ||||
| 137 | if $self->{ DEBUG }; | ||||
| 138 | |||||
| 139 | foreach my $provider (@$providers) { | ||||
| 140 | 9 | 775ms | ($template, $error) = $provider->fetch($shortname, $prefix); # spent 775ms making 9 calls to Template::Provider::fetch, avg 86.2ms/call | ||
| 141 | if ($error) { | ||||
| 142 | if ($error == Template::Constants::STATUS_ERROR) { | ||||
| 143 | # $template contains exception object | ||||
| 144 | if (blessed($template) && $template->isa(EXCEPTION) | ||||
| 145 | && $template->type eq Template::Constants::ERROR_FILE) { | ||||
| 146 | $self->throw($template); | ||||
| 147 | } | ||||
| 148 | else { | ||||
| 149 | $self->throw( Template::Constants::ERROR_FILE, $template ); | ||||
| 150 | } | ||||
| 151 | } | ||||
| 152 | # DECLINE is ok, carry on | ||||
| 153 | } | ||||
| 154 | elsif (length $blockname) { | ||||
| 155 | return $template | ||||
| 156 | if $template = $template->blocks->{ $blockname }; | ||||
| 157 | } | ||||
| 158 | else { | ||||
| 159 | return $template; | ||||
| 160 | } | ||||
| 161 | } | ||||
| 162 | |||||
| 163 | last if ref $shortname || ! $self->{ EXPOSE_BLOCKS }; | ||||
| 164 | $shortname =~ s{/([^/]+)$}{} || last; | ||||
| 165 | $blockname = length $blockname ? "$1/$blockname" : $1; | ||||
| 166 | } | ||||
| 167 | |||||
| 168 | $self->throw(Template::Constants::ERROR_FILE, "$name: not found"); | ||||
| 169 | } | ||||
| 170 | |||||
| 171 | |||||
| 172 | #------------------------------------------------------------------------ | ||||
| 173 | # plugin($name, \@args) | ||||
| 174 | # | ||||
| 175 | # Calls on each of the LOAD_PLUGINS providers in turn to fetch() (i.e. load | ||||
| 176 | # and instantiate) a plugin of the specified name. Additional parameters | ||||
| 177 | # passed are propagated to the new() constructor for the plugin. | ||||
| 178 | # Returns a reference to a new plugin object or other reference. On | ||||
| 179 | # error, undef is returned and the appropriate error message is set for | ||||
| 180 | # subsequent retrieval via error(). | ||||
| 181 | #------------------------------------------------------------------------ | ||||
| 182 | |||||
| 183 | sub plugin { | ||||
| 184 | my ($self, $name, $args) = @_; | ||||
| 185 | my ($provider, $plugin, $error); | ||||
| 186 | |||||
| 187 | $self->debug("plugin($name, ", defined $args ? @$args : '[ ]', ')') | ||||
| 188 | if $self->{ DEBUG }; | ||||
| 189 | |||||
| 190 | # request the named plugin from each of the LOAD_PLUGINS providers in turn | ||||
| 191 | foreach my $provider (@{ $self->{ LOAD_PLUGINS } }) { | ||||
| 192 | ($plugin, $error) = $provider->fetch($name, $args, $self); | ||||
| 193 | return $plugin unless $error; | ||||
| 194 | if ($error == Template::Constants::STATUS_ERROR) { | ||||
| 195 | $self->throw($plugin) if ref $plugin; | ||||
| 196 | $self->throw(Template::Constants::ERROR_PLUGIN, $plugin); | ||||
| 197 | } | ||||
| 198 | } | ||||
| 199 | |||||
| 200 | $self->throw(Template::Constants::ERROR_PLUGIN, "$name: plugin not found"); | ||||
| 201 | } | ||||
| 202 | |||||
| 203 | |||||
| 204 | #------------------------------------------------------------------------ | ||||
| 205 | # filter($name, \@args, $alias) | ||||
| 206 | # | ||||
| 207 | # Similar to plugin() above, but querying the LOAD_FILTERS providers to | ||||
| 208 | # return filter instances. An alias may be provided which is used to | ||||
| 209 | # save the returned filter in a local cache. | ||||
| 210 | #------------------------------------------------------------------------ | ||||
| 211 | |||||
| 212 | # spent 6.44ms (3.64+2.81) within Template::Context::filter which was called 214 times, avg 30µs/call:
# 101 times (2.04ms+1.58ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-facets.inc:32] at line 13 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-facets.inc, avg 36µs/call
# 60 times (583µs+476µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/page-numbers.inc:31] at line 7 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/page-numbers.inc, avg 18µs/call
# 25 times (482µs+320µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 505 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt, avg 32µs/call
# 5 times (161µs+126µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 5 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt, avg 57µs/call
# 4 times (40µs+31µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc:111] at line 72 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc, avg 18µs/call
# 4 times (36µs+29µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc:111] at line 91 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc, avg 16µs/call
# 4 times (35µs+27µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 385 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt, avg 16µs/call
# 3 times (87µs+53µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-facets.inc:32] at line 8 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-facets.inc, avg 47µs/call
# 2 times (24µs+19µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc:111] at line 98 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc, avg 21µs/call
# once (85µs+9µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 241 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (11µs+45µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 262 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (13µs+32µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 101 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (21µs+17µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc:111] at line 41 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc
# once (8µs+27µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 248 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (8µs+18µs) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 255 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt | ||||
| 213 | 2140 | 3.21ms | my ($self, $name, $args, $alias) = @_; | ||
| 214 | my ($provider, $filter, $error); | ||||
| 215 | |||||
| 216 | $self->debug("filter($name, ", | ||||
| 217 | defined $args ? @$args : '[ ]', | ||||
| 218 | defined $alias ? $alias : '<no alias>', ')') | ||||
| 219 | if $self->{ DEBUG }; | ||||
| 220 | |||||
| 221 | # use any cached version of the filter if no params provided | ||||
| 222 | return $filter | ||||
| 223 | if ! $args && ! ref $name | ||||
| 224 | && ($filter = $self->{ FILTER_CACHE }->{ $name }); | ||||
| 225 | |||||
| 226 | # request the named filter from each of the FILTERS providers in turn | ||||
| 227 | foreach my $provider (@{ $self->{ LOAD_FILTERS } }) { | ||||
| 228 | 214 | 2.81ms | ($filter, $error) = $provider->fetch($name, $args, $self); # spent 2.81ms making 214 calls to Template::Filters::fetch, avg 13µs/call | ||
| 229 | last unless $error; | ||||
| 230 | if ($error == Template::Constants::STATUS_ERROR) { | ||||
| 231 | $self->throw($filter) if ref $filter; | ||||
| 232 | $self->throw(Template::Constants::ERROR_FILTER, $filter); | ||||
| 233 | } | ||||
| 234 | # return $self->error($filter) | ||||
| 235 | # if $error == &Template::Constants::STATUS_ERROR; | ||||
| 236 | } | ||||
| 237 | |||||
| 238 | return $self->error("$name: filter not found") | ||||
| 239 | unless $filter; | ||||
| 240 | |||||
| 241 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 242 | # commented out by abw on 19 Nov 2001 to fix problem with xmlstyle | ||||
| 243 | # plugin which may re-define a filter by calling define_filter() | ||||
| 244 | # multiple times. With the automatic aliasing/caching below, any | ||||
| 245 | # new filter definition isn't seen. Don't think this will cause | ||||
| 246 | # any problems as filters explicitly supplied with aliases will | ||||
| 247 | # still work as expected. | ||||
| 248 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 249 | # alias defaults to name if undefined | ||||
| 250 | # $alias = $name | ||||
| 251 | # unless defined($alias) or ref($name) or $args; | ||||
| 252 | |||||
| 253 | # cache FILTER if alias is valid | ||||
| 254 | $self->{ FILTER_CACHE }->{ $alias } = $filter | ||||
| 255 | if $alias; | ||||
| 256 | |||||
| 257 | return $filter; | ||||
| 258 | } | ||||
| 259 | |||||
| 260 | |||||
| 261 | #------------------------------------------------------------------------ | ||||
| 262 | # view(\%config) | ||||
| 263 | # | ||||
| 264 | # Create a new Template::View bound to this context. | ||||
| 265 | #------------------------------------------------------------------------ | ||||
| 266 | |||||
| 267 | sub view { | ||||
| 268 | my $self = shift; | ||||
| 269 | require Template::View; | ||||
| 270 | return $VIEW_CLASS->new($self, @_) | ||||
| 271 | || $self->throw(&Template::Constants::ERROR_VIEW, | ||||
| 272 | $VIEW_CLASS->error); | ||||
| 273 | } | ||||
| 274 | |||||
| 275 | |||||
| 276 | #------------------------------------------------------------------------ | ||||
| 277 | # process($template, \%params) [% PROCESS template var=val ... %] | ||||
| 278 | # process($template, \%params, $local) [% INCLUDE template var=val ... %] | ||||
| 279 | # | ||||
| 280 | # Processes the template named or referenced by the first parameter. | ||||
| 281 | # The optional second parameter may reference a hash array of variable | ||||
| 282 | # definitions. These are set before the template is processed by | ||||
| 283 | # calling update() on the stash. Note that, unless the third parameter | ||||
| 284 | # is true, the context is not localised and these, and any other | ||||
| 285 | # variables set in the template will retain their new values after this | ||||
| 286 | # method returns. The third parameter is in place so that this method | ||||
| 287 | # can handle INCLUDE calls: the stash will be localized. | ||||
| 288 | # | ||||
| 289 | # Returns the output of processing the template. Errors are thrown | ||||
| 290 | # as Template::Exception objects via die(). | ||||
| 291 | #------------------------------------------------------------------------ | ||||
| 292 | |||||
| 293 | # spent 365ms (1.64+364) within Template::Context::process which was called 9 times, avg 40.6ms/call:
# 8 times (1.39ms+-1.39ms) by Template::Context::include at line 409, avg 0s/call
# once (246µs+365ms) by Template::Service::process at line 94 of Template/Service.pm | ||||
| 294 | 278 | 1.75ms | my ($self, $template, $params, $localize) = @_; | ||
| 295 | my ($trim, $blocks) = @$self{ qw( TRIM BLOCKS ) }; | ||||
| 296 | my (@compiled, $name, $compiled); | ||||
| 297 | my ($stash, $component, $tblocks, $error, $tmpout); | ||||
| 298 | my $output = ''; | ||||
| 299 | |||||
| 300 | $template = [ $template ] unless ref $template eq 'ARRAY'; | ||||
| 301 | |||||
| 302 | $self->debug("process([ ", join(', '), @$template, ' ], ', | ||||
| 303 | defined $params ? $params : '<no params>', ', ', | ||||
| 304 | $localize ? '<localized>' : '<unlocalized>', ')') | ||||
| 305 | if $self->{ DEBUG }; | ||||
| 306 | |||||
| 307 | # fetch compiled template for each name specified | ||||
| 308 | foreach $name (@$template) { | ||||
| 309 | 9 | 312ms | push(@compiled, $self->template($name)); # spent 312ms making 9 calls to Template::Context::template, avg 34.6ms/call | ||
| 310 | } | ||||
| 311 | |||||
| 312 | 8 | 1.51ms | if ($localize) { # spent 1.51ms making 8 calls to Template::Stash::clone, avg 188µs/call | ||
| 313 | # localise the variable stash with any parameters passed | ||||
| 314 | $stash = $self->{ STASH } = $self->{ STASH }->clone($params); | ||||
| 315 | } else { | ||||
| 316 | # update stash with any new parameters passed | ||||
| 317 | 1 | 9µs | $self->{ STASH }->update($params); # spent 9µs making 1 call to Template::Stash::update | ||
| 318 | $stash = $self->{ STASH }; | ||||
| 319 | } | ||||
| 320 | |||||
| 321 | eval { | ||||
| 322 | # save current component | ||||
| 323 | 1 | 18µs | 10 | 173µs | eval { $component = $stash->get('component') }; # spent 163µs making 9 calls to Template::Stash::XS::get, avg 18µs/call
# spent 11µs making 1 call to Template::Stash::undefined |
| 324 | |||||
| 325 | foreach $name (@$template) { | ||||
| 326 | $compiled = shift @compiled; | ||||
| 327 | my $element = ref $compiled eq 'CODE' | ||||
| 328 | ? { (name => (ref $name ? '' : $name), modtime => time()) } | ||||
| 329 | : $compiled; | ||||
| 330 | |||||
| 331 | 17 | 86µs | if (blessed($component) && $component->isa(DOCUMENT)) { # spent 66µs making 9 calls to Scalar::Util::blessed, avg 7µs/call
# spent 20µs making 8 calls to UNIVERSAL::isa, avg 3µs/call | ||
| 332 | $element->{ caller } = $component->{ name }; | ||||
| 333 | $element->{ callers } = $component->{ callers } || []; | ||||
| 334 | push(@{$element->{ callers }}, $element->{ caller }); | ||||
| 335 | } | ||||
| 336 | |||||
| 337 | 9 | 81µs | $stash->set('component', $element); # spent 81µs making 9 calls to Template::Stash::XS::set, avg 9µs/call | ||
| 338 | |||||
| 339 | 3 | 12µs | unless ($localize) { # spent 6µs making 1 call to Template::Document::blocks
# spent 4µs making 1 call to Scalar::Util::blessed
# spent 2µs making 1 call to UNIVERSAL::isa | ||
| 340 | # merge any local blocks defined in the Template::Document | ||||
| 341 | # into our local BLOCKS cache | ||||
| 342 | @$blocks{ keys %$tblocks } = values %$tblocks | ||||
| 343 | if (blessed($compiled) && $compiled->isa(DOCUMENT)) | ||||
| 344 | && ($tblocks = $compiled->blocks); | ||||
| 345 | } | ||||
| 346 | |||||
| 347 | 9 | 365ms | if (ref $compiled eq 'CODE') { # spent 393ms making 9 calls to Template::Document::process, avg 43.6ms/call, recursion: max depth 1, sum of overlapping time 27.8ms | ||
| 348 | $tmpout = &$compiled($self); | ||||
| 349 | } | ||||
| 350 | elsif (ref $compiled) { | ||||
| 351 | $tmpout = $compiled->process($self); | ||||
| 352 | } | ||||
| 353 | else { | ||||
| 354 | $self->throw('file', | ||||
| 355 | "invalid template reference: $compiled"); | ||||
| 356 | } | ||||
| 357 | |||||
| 358 | if ($trim) { | ||||
| 359 | for ($tmpout) { | ||||
| 360 | s/^\s+//; | ||||
| 361 | s/\s+$//; | ||||
| 362 | } | ||||
| 363 | } | ||||
| 364 | $output .= $tmpout; | ||||
| 365 | |||||
| 366 | # pop last item from callers. | ||||
| 367 | # NOTE - this will not be called if template throws an | ||||
| 368 | # error. The whole issue of caller and callers should be | ||||
| 369 | # revisited to try and avoid putting this info directly into | ||||
| 370 | # the component data structure. Perhaps use a local element | ||||
| 371 | # instead? | ||||
| 372 | |||||
| 373 | 17 | 48µs | pop(@{$element->{ callers }}) # spent 33µs making 9 calls to Scalar::Util::blessed, avg 4µs/call
# spent 14µs making 8 calls to UNIVERSAL::isa, avg 2µs/call | ||
| 374 | if (blessed($component) && $component->isa(DOCUMENT)); | ||||
| 375 | } | ||||
| 376 | 9 | 60µs | $stash->set('component', $component); # spent 60µs making 9 calls to Template::Stash::XS::set, avg 7µs/call | ||
| 377 | }; | ||||
| 378 | $error = $@; | ||||
| 379 | |||||
| 380 | 8 | 36µs | if ($localize) { # spent 36µs making 8 calls to Template::Stash::declone, avg 5µs/call | ||
| 381 | # ensure stash is delocalised before dying | ||||
| 382 | $self->{ STASH } = $self->{ STASH }->declone(); | ||||
| 383 | } | ||||
| 384 | |||||
| 385 | $self->throw(ref $error | ||||
| 386 | ? $error : (Template::Constants::ERROR_FILE, $error)) | ||||
| 387 | if $error; | ||||
| 388 | |||||
| 389 | return $output; | ||||
| 390 | } | ||||
| 391 | |||||
| 392 | |||||
| 393 | #------------------------------------------------------------------------ | ||||
| 394 | # include($template, \%params) [% INCLUDE template var = val, ... %] | ||||
| 395 | # | ||||
| 396 | # Similar to process() above but processing the template in a local | ||||
| 397 | # context. Any variables passed by reference to a hash as the second | ||||
| 398 | # parameter will be set before the template is processed and then | ||||
| 399 | # revert to their original values before the method returns. Similarly, | ||||
| 400 | # any changes made to non-global variables within the template will | ||||
| 401 | # persist only until the template is processed. | ||||
| 402 | # | ||||
| 403 | # Returns the output of processing the template. Errors are thrown | ||||
| 404 | # as Template::Exception objects via die(). | ||||
| 405 | #------------------------------------------------------------------------ | ||||
| 406 | |||||
| 407 | # spent 343ms (79µs+343) within Template::Context::include which was called 8 times, avg 42.9ms/call:
# 2 times (18µs+57.6ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 1 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt, avg 28.8ms/call
# once (9µs+97.7ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 313 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (11µs+80.2ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 525 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (15µs+63.9ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 532 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (9µs+20.7ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 317 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (9µs+19.6ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 389 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt
# once (9µs+2.96ms) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 518 of /usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt | ||||
| 408 | 16 | 137µs | my ($self, $template, $params) = @_; | ||
| 409 | 1 | 232µs | 16 | 27µs | return $self->process($template, $params, 'localize me!'); # spent 27µs making 8 calls to Template::Stash::XS::DESTROY, avg 3µs/call
# spent 343ms making 8 calls to Template::Context::process, avg 42.8ms/call, recursion: max depth 1, sum of overlapping time 343ms |
| 410 | } | ||||
| 411 | |||||
| 412 | #------------------------------------------------------------------------ | ||||
| 413 | # insert($file) | ||||
| 414 | # | ||||
| 415 | # Insert the contents of a file without parsing. | ||||
| 416 | #------------------------------------------------------------------------ | ||||
| 417 | |||||
| 418 | sub insert { | ||||
| 419 | my ($self, $file) = @_; | ||||
| 420 | my ($prefix, $providers, $text, $error); | ||||
| 421 | my $output = ''; | ||||
| 422 | |||||
| 423 | my $files = ref $file eq 'ARRAY' ? $file : [ $file ]; | ||||
| 424 | |||||
| 425 | $self->debug("insert([ ", join(', '), @$files, " ])") | ||||
| 426 | if $self->{ DEBUG }; | ||||
| 427 | |||||
| 428 | |||||
| 429 | FILE: foreach $file (@$files) { | ||||
| 430 | my $name = $file; | ||||
| 431 | |||||
| 432 | if ($^O eq 'MSWin32') { | ||||
| 433 | # let C:/foo through | ||||
| 434 | $prefix = $1 if $name =~ s/^(\w{2,})://o; | ||||
| 435 | } | ||||
| 436 | else { | ||||
| 437 | $prefix = $1 if $name =~ s/^(\w+)://; | ||||
| 438 | } | ||||
| 439 | |||||
| 440 | if (defined $prefix) { | ||||
| 441 | $providers = $self->{ PREFIX_MAP }->{ $prefix } | ||||
| 442 | || return $self->throw(Template::Constants::ERROR_FILE, | ||||
| 443 | "no providers for file prefix '$prefix'"); | ||||
| 444 | } | ||||
| 445 | else { | ||||
| 446 | $providers = $self->{ PREFIX_MAP }->{ default } | ||||
| 447 | || $self->{ LOAD_TEMPLATES }; | ||||
| 448 | } | ||||
| 449 | |||||
| 450 | foreach my $provider (@$providers) { | ||||
| 451 | ($text, $error) = $provider->load($name, $prefix); | ||||
| 452 | next FILE unless $error; | ||||
| 453 | if ($error == Template::Constants::STATUS_ERROR) { | ||||
| 454 | $self->throw($text) if ref $text; | ||||
| 455 | $self->throw(Template::Constants::ERROR_FILE, $text); | ||||
| 456 | } | ||||
| 457 | } | ||||
| 458 | $self->throw(Template::Constants::ERROR_FILE, "$file: not found"); | ||||
| 459 | } | ||||
| 460 | continue { | ||||
| 461 | $output .= $text; | ||||
| 462 | } | ||||
| 463 | return $output; | ||||
| 464 | } | ||||
| 465 | |||||
| 466 | |||||
| 467 | #------------------------------------------------------------------------ | ||||
| 468 | # throw($type, $info, \$output) [% THROW errtype "Error info" %] | ||||
| 469 | # | ||||
| 470 | # Throws a Template::Exception object by calling die(). This method | ||||
| 471 | # may be passed a reference to an existing Template::Exception object; | ||||
| 472 | # a single value containing an error message which is used to | ||||
| 473 | # instantiate a Template::Exception of type 'undef'; or a pair of | ||||
| 474 | # values representing the exception type and info from which a | ||||
| 475 | # Template::Exception object is instantiated. e.g. | ||||
| 476 | # | ||||
| 477 | # $context->throw($exception); | ||||
| 478 | # $context->throw("I'm sorry Dave, I can't do that"); | ||||
| 479 | # $context->throw('denied', "I'm sorry Dave, I can't do that"); | ||||
| 480 | # | ||||
| 481 | # An optional third parameter can be supplied in the last case which | ||||
| 482 | # is a reference to the current output buffer containing the results | ||||
| 483 | # of processing the template up to the point at which the exception | ||||
| 484 | # was thrown. The RETURN and STOP directives, for example, use this | ||||
| 485 | # to propagate output back to the user, but it can safely be ignored | ||||
| 486 | # in most cases. | ||||
| 487 | # | ||||
| 488 | # This method rides on a one-way ticket to die() oblivion. It does not | ||||
| 489 | # return in any real sense of the word, but should get caught by a | ||||
| 490 | # surrounding eval { } block (e.g. a BLOCK or TRY) and handled | ||||
| 491 | # accordingly, or returned to the caller as an uncaught exception. | ||||
| 492 | #------------------------------------------------------------------------ | ||||
| 493 | |||||
| 494 | sub throw { | ||||
| 495 | my ($self, $error, $info, $output) = @_; | ||||
| 496 | local $" = ', '; | ||||
| 497 | |||||
| 498 | # die! die! die! | ||||
| 499 | if (blessed($error) && $error->isa(EXCEPTION)) { | ||||
| 500 | die $error; | ||||
| 501 | } | ||||
| 502 | elsif (blessed($error) && $error->isa(BADGER_EXCEPTION)) { | ||||
| 503 | # convert a Badger::Exception to a Template::Exception so that | ||||
| 504 | # things continue to work during the transition to Badger | ||||
| 505 | die EXCEPTION->new($error->type, $error->info); | ||||
| 506 | } | ||||
| 507 | elsif (defined $info) { | ||||
| 508 | die (EXCEPTION->new($error, $info, $output)); | ||||
| 509 | } | ||||
| 510 | else { | ||||
| 511 | $error ||= ''; | ||||
| 512 | die (EXCEPTION->new('undef', $error, $output)); | ||||
| 513 | } | ||||
| 514 | |||||
| 515 | # not reached | ||||
| 516 | } | ||||
| 517 | |||||
| 518 | |||||
| 519 | #------------------------------------------------------------------------ | ||||
| 520 | # catch($error, \$output) | ||||
| 521 | # | ||||
| 522 | # Called by various directives after catching an error thrown via die() | ||||
| 523 | # from within an eval { } block. The first parameter contains the errror | ||||
| 524 | # which may be a sanitized reference to a Template::Exception object | ||||
| 525 | # (such as that raised by the throw() method above, a plugin object, | ||||
| 526 | # and so on) or an error message thrown via die from somewhere in user | ||||
| 527 | # code. The latter are coerced into 'undef' Template::Exception objects. | ||||
| 528 | # Like throw() above, a reference to a scalar may be passed as an | ||||
| 529 | # additional parameter to represent the current output buffer | ||||
| 530 | # localised within the eval block. As exceptions are thrown upwards | ||||
| 531 | # and outwards from nested blocks, the catch() method reconstructs the | ||||
| 532 | # correct output buffer from these fragments, storing it in the | ||||
| 533 | # exception object for passing further onwards and upwards. | ||||
| 534 | # | ||||
| 535 | # Returns a reference to a Template::Exception object.. | ||||
| 536 | #------------------------------------------------------------------------ | ||||
| 537 | |||||
| 538 | sub catch { | ||||
| 539 | my ($self, $error, $output) = @_; | ||||
| 540 | |||||
| 541 | if ( blessed($error) | ||||
| 542 | && ( $error->isa(EXCEPTION) || $error->isa(BADGER_EXCEPTION) ) ) { | ||||
| 543 | $error->text($output) if $output; | ||||
| 544 | return $error; | ||||
| 545 | } | ||||
| 546 | else { | ||||
| 547 | return EXCEPTION->new('undef', $error, $output); | ||||
| 548 | } | ||||
| 549 | } | ||||
| 550 | |||||
| 551 | |||||
| 552 | #------------------------------------------------------------------------ | ||||
| 553 | # localise(\%params) | ||||
| 554 | # delocalise() | ||||
| 555 | # | ||||
| 556 | # The localise() method creates a local copy of the current stash, | ||||
| 557 | # allowing the existing state of variables to be saved and later | ||||
| 558 | # restored via delocalise(). | ||||
| 559 | # | ||||
| 560 | # A reference to a hash array may be passed containing local variable | ||||
| 561 | # definitions which should be added to the cloned namespace. These | ||||
| 562 | # values persist until delocalisation. | ||||
| 563 | #------------------------------------------------------------------------ | ||||
| 564 | |||||
| 565 | # spent 301µs (39+261) within Template::Context::localise which was called:
# once (39µs+261µs) by Template::Service::process at line 78 of Template/Service.pm | ||||
| 566 | 2 | 34µs | my $self = shift; | ||
| 567 | 1 | 261µs | $self->{ STASH } = $self->{ STASH }->clone(@_); # spent 261µs making 1 call to Template::Stash::clone | ||
| 568 | } | ||||
| 569 | |||||
| 570 | # spent 92µs (86+6) within Template::Context::delocalise which was called:
# once (86µs+6µs) by Template::Service::process at line 124 of Template/Service.pm | ||||
| 571 | 2 | 16µs | my $self = shift; | ||
| 572 | 1 | 6µs | $self->{ STASH } = $self->{ STASH }->declone(); # spent 6µs making 1 call to Template::Stash::declone | ||
| 573 | } | ||||
| 574 | |||||
| 575 | |||||
| 576 | #------------------------------------------------------------------------ | ||||
| 577 | # visit($document, $blocks) | ||||
| 578 | # | ||||
| 579 | # Each Template::Document calls the visit() method on the context | ||||
| 580 | # before processing itself. It passes a reference to the hash array | ||||
| 581 | # of named BLOCKs defined within the document, allowing them to be | ||||
| 582 | # added to the internal BLKSTACK list which is subsequently used by | ||||
| 583 | # template() to resolve templates. | ||||
| 584 | # from a provider. | ||||
| 585 | #------------------------------------------------------------------------ | ||||
| 586 | |||||
| 587 | # spent 115µs within Template::Context::visit which was called 9 times, avg 13µs/call:
# 9 times (115µs+0s) by Template::Document::process at line 146 of Template/Document.pm, avg 13µs/call | ||||
| 588 | 18 | 128µs | my ($self, $document, $blocks) = @_; | ||
| 589 | unshift(@{ $self->{ BLKSTACK } }, $blocks) | ||||
| 590 | } | ||||
| 591 | |||||
| 592 | |||||
| 593 | #------------------------------------------------------------------------ | ||||
| 594 | # leave() | ||||
| 595 | # | ||||
| 596 | # The leave() method is called when the document has finished | ||||
| 597 | # processing itself. This removes the entry from the BLKSTACK list | ||||
| 598 | # that was added visit() above. For persistence of BLOCK definitions, | ||||
| 599 | # the process() method (i.e. the PROCESS directive) does some extra | ||||
| 600 | # magic to copy BLOCKs into a shared hash. | ||||
| 601 | #------------------------------------------------------------------------ | ||||
| 602 | |||||
| 603 | # spent 47µs within Template::Context::leave which was called 9 times, avg 5µs/call:
# 9 times (47µs+0s) by Template::Document::process at line 155 of Template/Document.pm, avg 5µs/call | ||||
| 604 | 18 | 62µs | my $self = shift; | ||
| 605 | shift(@{ $self->{ BLKSTACK } }); | ||||
| 606 | } | ||||
| 607 | |||||
| 608 | |||||
| 609 | #------------------------------------------------------------------------ | ||||
| 610 | # define_block($name, $block) | ||||
| 611 | # | ||||
| 612 | # Adds a new BLOCK definition to the local BLOCKS cache. $block may | ||||
| 613 | # be specified as a reference to a sub-routine or Template::Document | ||||
| 614 | # object or as text which is compiled into a template. Returns a true | ||||
| 615 | # value (the $block reference or compiled block reference) if | ||||
| 616 | # successful or undef on failure. Call error() to retrieve the | ||||
| 617 | # relevent error message (i.e. compilation failure). | ||||
| 618 | #------------------------------------------------------------------------ | ||||
| 619 | |||||
| 620 | sub define_block { | ||||
| 621 | my ($self, $name, $block) = @_; | ||||
| 622 | $block = $self->template(\$block) | ||||
| 623 | || return undef | ||||
| 624 | unless ref $block; | ||||
| 625 | $self->{ BLOCKS }->{ $name } = $block; | ||||
| 626 | } | ||||
| 627 | |||||
| 628 | |||||
| 629 | #------------------------------------------------------------------------ | ||||
| 630 | # define_filter($name, $filter, $is_dynamic) | ||||
| 631 | # | ||||
| 632 | # Adds a new FILTER definition to the local FILTER_CACHE. | ||||
| 633 | #------------------------------------------------------------------------ | ||||
| 634 | |||||
| 635 | sub define_filter { | ||||
| 636 | my ($self, $name, $filter, $is_dynamic) = @_; | ||||
| 637 | my ($result, $error); | ||||
| 638 | $filter = [ $filter, 1 ] if $is_dynamic; | ||||
| 639 | |||||
| 640 | foreach my $provider (@{ $self->{ LOAD_FILTERS } }) { | ||||
| 641 | ($result, $error) = $provider->store($name, $filter); | ||||
| 642 | return 1 unless $error; | ||||
| 643 | $self->throw(&Template::Constants::ERROR_FILTER, $result) | ||||
| 644 | if $error == &Template::Constants::STATUS_ERROR; | ||||
| 645 | } | ||||
| 646 | $self->throw(&Template::Constants::ERROR_FILTER, | ||||
| 647 | "FILTER providers declined to store filter $name"); | ||||
| 648 | } | ||||
| 649 | |||||
| 650 | sub define_view { | ||||
| 651 | my ($self, $name, $params) = @_; | ||||
| 652 | my $base; | ||||
| 653 | |||||
| 654 | if (defined $params->{ base }) { | ||||
| 655 | my $base = $self->{ STASH }->get($params->{ base }); | ||||
| 656 | |||||
| 657 | return $self->throw( | ||||
| 658 | &Template::Constants::ERROR_VIEW, | ||||
| 659 | "view base is not defined: $params->{ base }" | ||||
| 660 | ) unless $base; | ||||
| 661 | |||||
| 662 | return $self->throw( | ||||
| 663 | &Template::Constants::ERROR_VIEW, | ||||
| 664 | "view base is not a $VIEW_CLASS object: $params->{ base } => $base" | ||||
| 665 | ) unless blessed($base) && $base->isa($VIEW_CLASS); | ||||
| 666 | |||||
| 667 | $params->{ base } = $base; | ||||
| 668 | } | ||||
| 669 | my $view = $self->view($params); | ||||
| 670 | $view->seal(); | ||||
| 671 | $self->{ STASH }->set($name, $view); | ||||
| 672 | } | ||||
| 673 | |||||
| 674 | sub define_views { | ||||
| 675 | my ($self, $views) = @_; | ||||
| 676 | |||||
| 677 | # a list reference is better because the order is deterministic (and so | ||||
| 678 | # allows an earlier VIEW to be the base for a later VIEW), but we'll | ||||
| 679 | # accept a hash reference and assume that the user knows the order of | ||||
| 680 | # processing is undefined | ||||
| 681 | $views = [ %$views ] | ||||
| 682 | if ref $views eq 'HASH'; | ||||
| 683 | |||||
| 684 | # make of copy so we don't destroy the original list reference | ||||
| 685 | my @items = @$views; | ||||
| 686 | my ($name, $view); | ||||
| 687 | |||||
| 688 | while (@items) { | ||||
| 689 | $self->define_view(splice(@items, 0, 2)); | ||||
| 690 | } | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | |||||
| 694 | #------------------------------------------------------------------------ | ||||
| 695 | # reset() | ||||
| 696 | # | ||||
| 697 | # Reset the state of the internal BLOCKS hash to clear any BLOCK | ||||
| 698 | # definitions imported via the PROCESS directive. Any original | ||||
| 699 | # BLOCKS definitions passed to the constructor will be restored. | ||||
| 700 | #------------------------------------------------------------------------ | ||||
| 701 | |||||
| 702 | # spent 14µs within Template::Context::reset which was called:
# once (14µs+0s) by Template::Service::process at line 64 of Template/Service.pm | ||||
| 703 | 3 | 19µs | my ($self, $blocks) = @_; | ||
| 704 | $self->{ BLKSTACK } = [ ]; | ||||
| 705 | $self->{ BLOCKS } = { %{ $self->{ INIT_BLOCKS } } }; | ||||
| 706 | } | ||||
| 707 | |||||
| 708 | |||||
| 709 | #------------------------------------------------------------------------ | ||||
| 710 | # stash() | ||||
| 711 | # | ||||
| 712 | # Simple accessor methods to return the STASH values. This is likely | ||||
| 713 | # to be called quite often so we provide a direct method rather than | ||||
| 714 | # relying on the slower AUTOLOAD. | ||||
| 715 | #------------------------------------------------------------------------ | ||||
| 716 | |||||
| 717 | # spent 38µs within Template::Context::stash which was called 9 times, avg 4µs/call:
# 2 times (7µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/page-numbers.inc:31] at line 3 of (eval 1145)[Template/Document.pm:78], avg 3µs/call
# once (6µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-bottom.inc:74] at line 3 of (eval 1148)[Template/Document.pm:78]
# once (6µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/modules/opac-results.tt:541] at line 3 of (eval 1141)[Template/Document.pm:78]
# once (6µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/opac-facets.inc:32] at line 3 of (eval 1147)[Template/Document.pm:78]
# once (4µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/doc-head-close.inc:121] at line 3 of (eval 1143)[Template/Document.pm:78]
# once (3µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/resort_form.inc:48] at line 3 of (eval 1146)[Template/Document.pm:78]
# once (3µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/masthead.inc:111] at line 3 of (eval 1144)[Template/Document.pm:78]
# once (2µs+0s) by Template::Document::__ANON__[/usr/share/koha/opac/htdocs/opac-tmpl/prog/en-NZ/includes/doc-head-open.inc:14] at line 3 of (eval 1142)[Template/Document.pm:78] | ||||
| 718 | 9 | 77µs | return $_[0]->{ STASH }; | ||
| 719 | } | ||||
| 720 | |||||
| 721 | |||||
| 722 | #------------------------------------------------------------------------ | ||||
| 723 | # define_vmethod($type, $name, \&sub) | ||||
| 724 | # | ||||
| 725 | # Passes $type, $name, and &sub on to stash->define_vmethod(). | ||||
| 726 | #------------------------------------------------------------------------ | ||||
| 727 | sub define_vmethod { | ||||
| 728 | my $self = shift; | ||||
| 729 | $self->stash->define_vmethod(@_); | ||||
| 730 | } | ||||
| 731 | |||||
| 732 | |||||
| 733 | #------------------------------------------------------------------------ | ||||
| 734 | # debugging($command, @args, \%params) | ||||
| 735 | # | ||||
| 736 | # Method for controlling the debugging status of the context. The first | ||||
| 737 | # argument can be 'on' or 'off' to enable/disable debugging, 'format' | ||||
| 738 | # to define the format of the debug message, or 'msg' to generate a | ||||
| 739 | # debugging message reporting the file, line, message text, etc., | ||||
| 740 | # according to the current debug format. | ||||
| 741 | #------------------------------------------------------------------------ | ||||
| 742 | |||||
| 743 | sub debugging { | ||||
| 744 | my $self = shift; | ||||
| 745 | my $hash = ref $_[-1] eq 'HASH' ? pop : { }; | ||||
| 746 | my @args = @_; | ||||
| 747 | |||||
| 748 | # print "*** debug(@args)\n"; | ||||
| 749 | if (@args) { | ||||
| 750 | if ($args[0] =~ /^on|1$/i) { | ||||
| 751 | $self->{ DEBUG_DIRS } = 1; | ||||
| 752 | shift(@args); | ||||
| 753 | } | ||||
| 754 | elsif ($args[0] =~ /^off|0$/i) { | ||||
| 755 | $self->{ DEBUG_DIRS } = 0; | ||||
| 756 | shift(@args); | ||||
| 757 | } | ||||
| 758 | } | ||||
| 759 | |||||
| 760 | if (@args) { | ||||
| 761 | if ($args[0] =~ /^msg$/i) { | ||||
| 762 | return unless $self->{ DEBUG_DIRS }; | ||||
| 763 | my $format = $self->{ DEBUG_FORMAT }; | ||||
| 764 | $format = $DEBUG_FORMAT unless defined $format; | ||||
| 765 | $format =~ s/\$(\w+)/$hash->{ $1 }/ge; | ||||
| 766 | return $format; | ||||
| 767 | } | ||||
| 768 | elsif ($args[0] =~ /^format$/i) { | ||||
| 769 | $self->{ DEBUG_FORMAT } = $args[1]; | ||||
| 770 | } | ||||
| 771 | # else ignore | ||||
| 772 | } | ||||
| 773 | |||||
| 774 | return ''; | ||||
| 775 | } | ||||
| 776 | |||||
| 777 | |||||
| 778 | #------------------------------------------------------------------------ | ||||
| 779 | # AUTOLOAD | ||||
| 780 | # | ||||
| 781 | # Provides pseudo-methods for read-only access to various internal | ||||
| 782 | # members. For example, templates(), plugins(), filters(), | ||||
| 783 | # eval_perl(), load_perl(), etc. These aren't called very often, or | ||||
| 784 | # may never be called at all. | ||||
| 785 | #------------------------------------------------------------------------ | ||||
| 786 | |||||
| 787 | sub AUTOLOAD { | ||||
| 788 | my $self = shift; | ||||
| 789 | my $method = $AUTOLOAD; | ||||
| 790 | my $result; | ||||
| 791 | |||||
| 792 | $method =~ s/.*:://; | ||||
| 793 | return if $method eq 'DESTROY'; | ||||
| 794 | |||||
| 795 | warn "no such context method/member: $method\n" | ||||
| 796 | unless defined ($result = $self->{ uc $method }); | ||||
| 797 | |||||
| 798 | return $result; | ||||
| 799 | } | ||||
| 800 | |||||
| 801 | |||||
| 802 | #------------------------------------------------------------------------ | ||||
| 803 | # DESTROY | ||||
| 804 | # | ||||
| 805 | # Stash may contain references back to the Context via macro closures, | ||||
| 806 | # etc. This breaks the circular references. | ||||
| 807 | #------------------------------------------------------------------------ | ||||
| 808 | |||||
| 809 | # spent 15µs within Template::Context::DESTROY which was called:
# once (15µs+0s) by main::NULL at line 0 of /usr/share/koha/opac/cgi-bin/opac/opac-search.pl | ||||
| 810 | 2 | 17µs | my $self = shift; | ||
| 811 | undef $self->{ STASH }; | ||||
| 812 | } | ||||
| 813 | |||||
| - - | |||||
| 816 | #======================================================================== | ||||
| 817 | # -- PRIVATE METHODS -- | ||||
| 818 | #======================================================================== | ||||
| 819 | |||||
| 820 | #------------------------------------------------------------------------ | ||||
| 821 | # _init(\%config) | ||||
| 822 | # | ||||
| 823 | # Initialisation method called by Template::Base::new() | ||||
| 824 | #------------------------------------------------------------------------ | ||||
| 825 | |||||
| 826 | # spent 18.3ms (124µs+18.1) within Template::Context::_init which was called:
# once (124µs+18.1ms) by Template::Base::new at line 65 of Template/Base.pm | ||||
| 827 | 31 | 120µs | my ($self, $config) = @_; | ||
| 828 | my ($name, $item, $method, $block, $blocks); | ||||
| 829 | my @itemlut = ( | ||||
| 830 | LOAD_TEMPLATES => 'provider', | ||||
| 831 | LOAD_PLUGINS => 'plugins', | ||||
| 832 | LOAD_FILTERS => 'filters' | ||||
| 833 | ); | ||||
| 834 | |||||
| 835 | # LOAD_TEMPLATE, LOAD_PLUGINS, LOAD_FILTERS - lists of providers | ||||
| 836 | while (($name, $method) = splice(@itemlut, 0, 2)) { | ||||
| 837 | 3 | 6.13ms | $item = $config->{ $name } # spent 4.14ms making 1 call to Template::Config::filters
# spent 1.87ms making 1 call to Template::Config::plugins
# spent 124µs making 1 call to Template::Config::provider | ||
| 838 | || Template::Config->$method($config) | ||||
| 839 | || return $self->error($Template::Config::ERROR); | ||||
| 840 | $self->{ $name } = ref $item eq 'ARRAY' ? $item : [ $item ]; | ||||
| 841 | } | ||||
| 842 | |||||
| 843 | my $providers = $self->{ LOAD_TEMPLATES }; | ||||
| 844 | my $prefix_map = $self->{ PREFIX_MAP } = $config->{ PREFIX_MAP } || { }; | ||||
| 845 | while (my ($key, $val) = each %$prefix_map) { | ||||
| 846 | $prefix_map->{ $key } = [ ref $val ? $val : | ||||
| 847 | map { $providers->[$_] } split(/\D+/, $val) ] | ||||
| 848 | unless ref $val eq 'ARRAY'; | ||||
| 849 | } | ||||
| 850 | |||||
| 851 | # STASH | ||||
| 852 | $self->{ STASH } = $config->{ STASH } || do { | ||||
| 853 | my $predefs = $config->{ VARIABLES } | ||||
| 854 | || $config->{ PRE_DEFINE } | ||||
| 855 | || { }; | ||||
| 856 | |||||
| 857 | # hack to get stash to know about debug mode | ||||
| 858 | $predefs->{ _DEBUG } = ( ($config->{ DEBUG } || 0) | ||||
| 859 | & &Template::Constants::DEBUG_UNDEF ) ? 1 : 0 | ||||
| 860 | 1 | 3µs | unless defined $predefs->{ _DEBUG }; # spent 3µs making 1 call to Template::Constants::DEBUG_UNDEF | ||
| 861 | $predefs->{ _STRICT } = $config->{ STRICT }; | ||||
| 862 | |||||
| 863 | 1 | 12.0ms | Template::Config->stash($predefs) # spent 12.0ms making 1 call to Template::Config::stash | ||
| 864 | || return $self->error($Template::Config::ERROR); | ||||
| 865 | }; | ||||
| 866 | |||||
| 867 | # compile any template BLOCKS specified as text | ||||
| 868 | $blocks = $config->{ BLOCKS } || { }; | ||||
| 869 | $self->{ INIT_BLOCKS } = $self->{ BLOCKS } = { | ||||
| 870 | map { | ||||
| 871 | $block = $blocks->{ $_ }; | ||||
| 872 | $block = $self->template(\$block) | ||||
| 873 | || return undef | ||||
| 874 | unless ref $block; | ||||
| 875 | ($_ => $block); | ||||
| 876 | } | ||||
| 877 | keys %$blocks | ||||
| 878 | }; | ||||
| 879 | |||||
| 880 | # define any VIEWS | ||||
| 881 | $self->define_views( $config->{ VIEWS } ) | ||||
| 882 | if $config->{ VIEWS }; | ||||
| 883 | |||||
| 884 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 885 | # RECURSION - flag indicating is recursion into templates is supported | ||||
| 886 | # EVAL_PERL - flag indicating if PERL blocks should be processed | ||||
| 887 | # TRIM - flag to remove leading and trailing whitespace from output | ||||
| 888 | # BLKSTACK - list of hashes of BLOCKs defined in current template(s) | ||||
| 889 | # CONFIG - original configuration hash | ||||
| 890 | # EXPOSE_BLOCKS - make blocks visible as pseudo-files | ||||
| 891 | # DEBUG_FORMAT - format for generating template runtime debugging messages | ||||
| 892 | # DEBUG - format for generating template runtime debugging messages | ||||
| 893 | |||||
| 894 | $self->{ RECURSION } = $config->{ RECURSION } || 0; | ||||
| 895 | $self->{ EVAL_PERL } = $config->{ EVAL_PERL } || 0; | ||||
| 896 | $self->{ TRIM } = $config->{ TRIM } || 0; | ||||
| 897 | $self->{ BLKSTACK } = [ ]; | ||||
| 898 | $self->{ CONFIG } = $config; | ||||
| 899 | $self->{ EXPOSE_BLOCKS } = defined $config->{ EXPOSE_BLOCKS } | ||||
| 900 | ? $config->{ EXPOSE_BLOCKS } | ||||
| 901 | : 0; | ||||
| 902 | |||||
| 903 | $self->{ DEBUG_FORMAT } = $config->{ DEBUG_FORMAT }; | ||||
| 904 | $self->{ DEBUG_DIRS } = ($config->{ DEBUG } || 0) | ||||
| 905 | & Template::Constants::DEBUG_DIRS; | ||||
| 906 | $self->{ DEBUG } = defined $config->{ DEBUG } | ||||
| 907 | ? $config->{ DEBUG } & ( Template::Constants::DEBUG_CONTEXT | ||||
| 908 | | Template::Constants::DEBUG_FLAGS ) | ||||
| 909 | : $DEBUG; | ||||
| 910 | |||||
| 911 | return $self; | ||||
| 912 | } | ||||
| 913 | |||||
| 914 | |||||
| 915 | #------------------------------------------------------------------------ | ||||
| 916 | # _dump() | ||||
| 917 | # | ||||
| 918 | # Debug method which returns a string representing the internal state | ||||
| 919 | # of the context object. | ||||
| 920 | #------------------------------------------------------------------------ | ||||
| 921 | |||||
| 922 | sub _dump { | ||||
| 923 | my $self = shift; | ||||
| 924 | my $output = "[Template::Context] {\n"; | ||||
| 925 | my $format = " %-16s => %s\n"; | ||||
| 926 | my $key; | ||||
| 927 | |||||
| 928 | foreach $key (qw( RECURSION EVAL_PERL TRIM )) { | ||||
| 929 | $output .= sprintf($format, $key, $self->{ $key }); | ||||
| 930 | } | ||||
| 931 | foreach my $pname (qw( LOAD_TEMPLATES LOAD_PLUGINS LOAD_FILTERS )) { | ||||
| 932 | my $provtext = "[\n"; | ||||
| 933 | foreach my $prov (@{ $self->{ $pname } }) { | ||||
| 934 | $provtext .= $prov->_dump(); | ||||
| 935 | # $provtext .= ",\n"; | ||||
| 936 | } | ||||
| 937 | $provtext =~ s/\n/\n /g; | ||||
| 938 | $provtext =~ s/\s+$//; | ||||
| 939 | $provtext .= ",\n ]"; | ||||
| 940 | $output .= sprintf($format, $pname, $provtext); | ||||
| 941 | } | ||||
| 942 | $output .= sprintf($format, STASH => $self->{ STASH }->_dump()); | ||||
| 943 | $output .= '}'; | ||||
| 944 | return $output; | ||||
| 945 | } | ||||
| 946 | |||||
| 947 | |||||
| 948 | 1 | 7µs | 1; | ||
| 949 | |||||
| 950 | __END__ | ||||
# spent 22µs within Template::Context::CORE:subst which was called 9 times, avg 2µs/call:
# 9 times (22µs+0s) by Template::Context::template at line 116, avg 2µs/call |