| Filename | /usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Context.pm |
| Statements | Executed 666 statements in 1.75ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 40 | 2 | 2 | 3.32ms | 480ms | Template::Context::process (recurses: max depth 2, inclusive time 566ms) |
| 44 | 2 | 2 | 1.16ms | 475ms | Template::Context::template |
| 4 | 1 | 1 | 273µs | 16.3ms | Template::Context::_init |
| 25 | 7 | 5 | 228µs | 7.87ms | Template::Context::plugin |
| 36 | 15 | 5 | 210µs | 474ms | Template::Context::include (recurses: max depth 1, inclusive time 92.0ms) |
| 40 | 1 | 1 | 128µs | 128µs | Template::Context::visit |
| 40 | 1 | 1 | 92µs | 92µs | Template::Context::leave |
| 40 | 12 | 12 | 88µs | 88µs | Template::Context::stash |
| 40 | 1 | 1 | 84µs | 84µs | Template::Context::CORE:subst (opcode) |
| 4 | 1 | 1 | 77µs | 600µs | Template::Context::localise |
| 4 | 1 | 1 | 28µs | 28µs | Template::Context::reset |
| 4 | 1 | 1 | 21µs | 26µs | Template::Context::delocalise |
| 1 | 1 | 1 | 20µs | 32µs | Template::Context::BEGIN@23 |
| 4 | 2 | 2 | 18µs | 18µs | Template::Context::DESTROY |
| 1 | 1 | 1 | 14µs | 66µs | Template::Context::BEGIN@25 |
| 1 | 1 | 1 | 11µs | 33µs | Template::Context::BEGIN@29 |
| 1 | 1 | 1 | 11µs | 42µs | Template::Context::BEGIN@33 |
| 1 | 1 | 1 | 10µs | 31µs | Template::Context::BEGIN@31 |
| 1 | 1 | 1 | 10µs | 19µs | Template::Context::BEGIN@24 |
| 1 | 1 | 1 | 9µs | 9µs | Template::Context::BEGIN@27 |
| 1 | 1 | 1 | 8µs | 22µs | Template::Context::BEGIN@34 |
| 1 | 1 | 1 | 7µs | 7µs | Template::Context::BEGIN@30 |
| 1 | 1 | 1 | 7µs | 22µs | Template::Context::BEGIN@35 |
| 1 | 1 | 1 | 5µs | 5µs | Template::Context::BEGIN@28 |
| 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::filter |
| 0 | 0 | 0 | 0s | 0s | Template::Context::insert |
| 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 | 2 | 45µs | # spent 32µs (20+13) within Template::Context::BEGIN@23 which was called:
# once (20µs+13µs) by Template::Config::load at line 23 # spent 32µs making 1 call to Template::Context::BEGIN@23
# spent 13µs making 1 call to strict::import | ||
| 24 | 2 | 29µs | # spent 19µs (10+9) within Template::Context::BEGIN@24 which was called:
# once (10µs+9µs) by Template::Config::load at line 24 # spent 19µs making 1 call to Template::Context::BEGIN@24
# spent 9µs making 1 call to warnings::import | ||
| 25 | 2 | 119µs | # spent 66µs (14+53) within Template::Context::BEGIN@25 which was called:
# once (14µs+53µs) by Template::Config::load at line 25 # spent 66µs making 1 call to Template::Context::BEGIN@25
# spent 53µs making 1 call to base::import | ||
| 26 | |||||
| 27 | 1 | 9µs | # spent 9µs within Template::Context::BEGIN@27 which was called:
# once (9µs+0s) by Template::Config::load at line 27 # spent 9µs making 1 call to Template::Context::BEGIN@27 | ||
| 28 | 1 | 5µs | # spent 5µs within Template::Context::BEGIN@28 which was called:
# once (5µs+0s) by Template::Config::load at line 28 # spent 5µs making 1 call to Template::Context::BEGIN@28 | ||
| 29 | 2 | 56µs | # spent 33µs (11+23) within Template::Context::BEGIN@29 which was called:
# once (11µs+23µs) by Template::Config::load at line 29 # spent 33µs making 1 call to Template::Context::BEGIN@29
# spent 22µs making 1 call to Exporter::import | ||
| 30 | 1 | 7µs | # spent 7µs within Template::Context::BEGIN@30 which was called:
# once (7µs+0s) by Template::Config::load at line 30 # spent 7µs making 1 call to Template::Context::BEGIN@30 | ||
| 31 | 2 | 52µs | # spent 31µs (10+21) within Template::Context::BEGIN@31 which was called:
# once (10µs+21µs) by Template::Config::load at line 31 # spent 31µs making 1 call to Template::Context::BEGIN@31
# spent 21µs making 1 call to Exporter::import | ||
| 32 | |||||
| 33 | 2 | 73µs | # spent 42µs (11+31) within Template::Context::BEGIN@33 which was called:
# once (11µs+31µs) by Template::Config::load at line 33 # spent 42µs making 1 call to Template::Context::BEGIN@33
# spent 31µs making 1 call to constant::import | ||
| 34 | 2 | 36µs | # spent 22µs (8+14) within Template::Context::BEGIN@34 which was called:
# once (8µs+14µs) by Template::Config::load at line 34 # spent 22µs making 1 call to Template::Context::BEGIN@34
# spent 14µs making 1 call to constant::import | ||
| 35 | 2 | 36µs | # spent 22µs (7+14) within Template::Context::BEGIN@35 which was called:
# once (7µs+14µs) by Template::Config::load at line 35 # spent 22µs making 1 call to Template::Context::BEGIN@35
# spent 14µs making 1 call to constant::import | ||
| 36 | |||||
| 37 | our $VERSION = 2.98; | ||||
| 38 | our $DEBUG = 0 unless defined $DEBUG; | ||||
| 39 | our $DEBUG_FORMAT = "\n## \$file line \$line : [% \$text %] ##\n"; | ||||
| 40 | our $VIEW_CLASS = 'Template::View'; | ||||
| 41 | 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 475ms (1.16+474) within Template::Context::template which was called 44 times, avg 10.8ms/call:
# 40 times (1.03ms+408ms) by Template::Context::process at line 309, avg 10.2ms/call
# 4 times (131µs+65.5ms) by Template::Service::process at line 68 of Template/Service.pm, avg 16.4ms/call | ||||
| 78 | 11 | 4µs | my ($self, $name) = @_; | ||
| 79 | 11 | 3µs | my ($prefix, $blocks, $defblocks, $provider, $template, $error); | ||
| 80 | my ($shortname, $blockname, $providers); | ||||
| 81 | |||||
| 82 | 11 | 5µs | $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 | 57µs | 48 | 54µs | return $name # spent 44µs making 44 calls to Scalar::Util::blessed, avg 1µs/call
# spent 10µs making 4 calls to UNIVERSAL::isa, avg 2µs/call |
| 88 | if (blessed($name) && $name->isa(DOCUMENT)) | ||||
| 89 | || ref($name) eq 'CODE'; | ||||
| 90 | |||||
| 91 | 10 | 3µs | $shortname = $name; | ||
| 92 | |||||
| 93 | 10 | 11µs | unless (ref $name) { | ||
| 94 | |||||
| 95 | 10 | 5µs | $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 | 10 | 8µs | 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 | 10 | 13µs | foreach $blocks (@{ $self->{ BLKSTACK } }) { | ||
| 105 | 13 | 15µs | 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 | 10 | 24µs | if ($^O eq 'MSWin32') { | ||
| 112 | # let C:/foo through | ||||
| 113 | $prefix = $1 if $shortname =~ s/^(\w{2,})://o; | ||||
| 114 | } | ||||
| 115 | else { | ||||
| 116 | 10 | 48µs | 40 | 84µs | $prefix = $1 if $shortname =~ s/^(\w+)://; # spent 84µs making 40 calls to Template::Context::CORE:subst, avg 2µs/call |
| 117 | } | ||||
| 118 | |||||
| 119 | 10 | 5µs | 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 | 10 | 20µs | 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 | 10 | 6µs | $blockname = ''; | ||
| 135 | 10 | 4µs | while ($shortname) { | ||
| 136 | $self->debug("asking providers for [$shortname] [$blockname]") | ||||
| 137 | 10 | 4µs | if $self->{ DEBUG }; | ||
| 138 | |||||
| 139 | 10 | 9µs | foreach my $provider (@$providers) { | ||
| 140 | 10 | 35µs | 40 | 474ms | ($template, $error) = $provider->fetch($shortname, $prefix); # spent 474ms making 40 calls to Template::Provider::fetch, avg 11.8ms/call |
| 141 | 10 | 10µs | 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 | 10 | 42µs | 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 | # spent 7.87ms (228µs+7.64) within Template::Context::plugin which was called 25 times, avg 315µs/call:
# 4 times (22µs+2.51ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 4 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 634µs/call
# 4 times (47µs+1.88ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-open.inc:36] at line 5 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-open.inc, avg 482µs/call
# 4 times (48µs+1.76ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc:120] at line 2 of koha-tmpl/intranet-tmpl/prog/en/includes/header.inc, avg 452µs/call
# 4 times (17µs+1.24ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 3 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 315µs/call
# 4 times (42µs+88µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search-box.inc:62] at line 2 of koha-tmpl/intranet-tmpl/prog/en/includes/patron-search-box.inc, avg 32µs/call
# 4 times (42µs+83µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 2 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 31µs/call
# once (12µs+72µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 2 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt | ||||
| 184 | 7 | 4µs | my ($self, $name, $args) = @_; | ||
| 185 | 7 | 1µs | my ($provider, $plugin, $error); | ||
| 186 | |||||
| 187 | $self->debug("plugin($name, ", defined $args ? @$args : '[ ]', ')') | ||||
| 188 | 7 | 5µs | if $self->{ DEBUG }; | ||
| 189 | |||||
| 190 | # request the named plugin from each of the LOAD_PLUGINS providers in turn | ||||
| 191 | 7 | 10µs | foreach my $provider (@{ $self->{ LOAD_PLUGINS } }) { | ||
| 192 | 7 | 22µs | 25 | 7.64ms | ($plugin, $error) = $provider->fetch($name, $args, $self); # spent 7.64ms making 25 calls to Template::Plugins::fetch, avg 306µs/call |
| 193 | 7 | 30µs | 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 | sub filter { | ||||
| 213 | 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 | ($filter, $error) = $provider->fetch($name, $args, $self); | ||||
| 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 480ms (3.32+477) within Template::Context::process which was called 40 times, avg 12.0ms/call:
# 36 times (3.03ms+-3.03ms) by Template::Context::include at line 409, avg 0s/call
# 4 times (290µs+480ms) by Template::Service::process at line 94 of Template/Service.pm, avg 120ms/call | ||||
| 294 | 10 | 6µs | my ($self, $template, $params, $localize) = @_; | ||
| 295 | 10 | 15µs | my ($trim, $blocks) = @$self{ qw( TRIM BLOCKS ) }; | ||
| 296 | 10 | 2µs | my (@compiled, $name, $compiled); | ||
| 297 | my ($stash, $component, $tblocks, $error, $tmpout); | ||||
| 298 | 10 | 4µs | my $output = ''; | ||
| 299 | |||||
| 300 | 10 | 14µs | $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 | 10 | 7µs | if $self->{ DEBUG }; | ||
| 306 | |||||
| 307 | # fetch compiled template for each name specified | ||||
| 308 | 10 | 11µs | foreach $name (@$template) { | ||
| 309 | 10 | 44µs | 40 | 409ms | push(@compiled, $self->template($name)); # spent 409ms making 40 calls to Template::Context::template, avg 10.2ms/call |
| 310 | } | ||||
| 311 | |||||
| 312 | 10 | 64µs | 36 | 4.36ms | if ($localize) { # spent 4.36ms making 36 calls to Template::Stash::clone, avg 121µ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 | 4µs | 4 | 24µs | $self->{ STASH }->update($params); # spent 24µs making 4 calls to Template::Stash::update, avg 6µs/call |
| 318 | 1 | 800ns | $stash = $self->{ STASH }; | ||
| 319 | } | ||||
| 320 | |||||
| 321 | 10 | 7µs | eval { | ||
| 322 | # save current component | ||||
| 323 | 20 | 133µs | 44 | 409µs | eval { $component = $stash->get('component') }; # spent 391µs making 40 calls to Template::Stash::XS::get, avg 10µs/call
# spent 18µs making 4 calls to Template::Stash::undefined, avg 4µs/call |
| 324 | |||||
| 325 | 10 | 11µs | foreach $name (@$template) { | ||
| 326 | 10 | 6µs | $compiled = shift @compiled; | ||
| 327 | 10 | 11µs | my $element = ref $compiled eq 'CODE' | ||
| 328 | ? { (name => (ref $name ? '' : $name), modtime => time()) } | ||||
| 329 | : $compiled; | ||||
| 330 | |||||
| 331 | 10 | 109µs | 76 | 188µs | if (blessed($component) && $component->isa(DOCUMENT)) { # spent 118µs making 40 calls to Scalar::Util::blessed, avg 3µs/call
# spent 70µs making 36 calls to UNIVERSAL::isa, avg 2µs/call |
| 332 | 9 | 15µs | $element->{ caller } = $component->{ name }; | ||
| 333 | 9 | 16µs | $element->{ callers } = $component->{ callers } || []; | ||
| 334 | 9 | 9µs | push(@{$element->{ callers }}, $element->{ caller }); | ||
| 335 | } | ||||
| 336 | |||||
| 337 | 10 | 72µs | 40 | 171µs | $stash->set('component', $element); # spent 171µs making 40 calls to Template::Stash::XS::set, avg 4µs/call |
| 338 | |||||
| 339 | 10 | 12µs | 12 | 14µs | unless ($localize) { # spent 9µs making 4 calls to Template::Document::blocks, avg 2µs/call
# spent 3µs making 4 calls to Scalar::Util::blessed, avg 850ns/call
# spent 2µs making 4 calls to UNIVERSAL::isa, avg 550ns/call |
| 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 | 10 | 45µs | 40 | 479ms | if (ref $compiled eq 'CODE') { # spent 627ms making 40 calls to Template::Document::process, avg 15.7ms/call, recursion: max depth 2, sum of overlapping time 148ms |
| 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 | 10 | 2µs | if ($trim) { | ||
| 359 | for ($tmpout) { | ||||
| 360 | s/^\s+//; | ||||
| 361 | s/\s+$//; | ||||
| 362 | } | ||||
| 363 | } | ||||
| 364 | 10 | 23µs | $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 | 10 | 81µs | 76 | 86µs | pop(@{$element->{ callers }}) # spent 56µs making 40 calls to Scalar::Util::blessed, avg 1µs/call
# spent 30µs making 36 calls to UNIVERSAL::isa, avg 822ns/call |
| 374 | if (blessed($component) && $component->isa(DOCUMENT)); | ||||
| 375 | } | ||||
| 376 | 10 | 67µs | 40 | 136µs | $stash->set('component', $component); # spent 136µs making 40 calls to Template::Stash::XS::set, avg 3µs/call |
| 377 | }; | ||||
| 378 | 10 | 4µs | $error = $@; | ||
| 379 | |||||
| 380 | 10 | 24µs | 36 | 72µs | if ($localize) { # spent 72µs making 36 calls to Template::Stash::declone, avg 2µs/call |
| 381 | # ensure stash is delocalised before dying | ||||
| 382 | $self->{ STASH } = $self->{ STASH }->declone(); | ||||
| 383 | } | ||||
| 384 | |||||
| 385 | 10 | 2µs | $self->throw(ref $error | ||
| 386 | ? $error : (Template::Constants::ERROR_FILE, $error)) | ||||
| 387 | if $error; | ||||
| 388 | |||||
| 389 | 10 | 42µs | 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 474ms (210µs+474) within Template::Context::include which was called 36 times, avg 13.2ms/call:
# 4 times (33µs+-33µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 90 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 0s/call
# 4 times (29µs+-29µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 11 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 0s/call
# 4 times (20µs+-20µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 30 of koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc, avg 0s/call
# 3 times (13µs+147ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 3 of koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt, avg 49.0ms/call
# 3 times (15µs+80.0ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 36 of koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt, avg 26.7ms/call
# 3 times (16µs+65.3ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 7 of koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt, avg 21.8ms/call
# 3 times (14µs+54.4ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 8 of koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt, avg 18.1ms/call
# 3 times (18µs+38.2ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 1 of koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt, avg 12.7ms/call
# 3 times (18µs+-18µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/cat-search.inc:41] at line 5 of koha-tmpl/intranet-tmpl/prog/en/includes/cat-search.inc, avg 0s/call
# once (4µs+32.7ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 5 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
# once (7µs+21.5ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 194 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
# once (6µs+13.3ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 10 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
# once (5µs+11.7ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 11 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
# once (6µs+9.83ms) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 2 of koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
# once (7µs+-7µs) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/home-search.inc:48] at line 5 of koha-tmpl/intranet-tmpl/prog/en/includes/home-search.inc | ||||
| 408 | 9 | 6µs | my ($self, $template, $params) = @_; | ||
| 409 | 9 | 242µs | 72 | 70µs | return $self->process($template, $params, 'localize me!'); # spent 70µs making 36 calls to Template::Stash::XS::DESTROY, avg 2µs/call
# spent 566ms making 36 calls to Template::Context::process, avg 15.7ms/call, recursion: max depth 2, sum of overlapping time 566ms |
| 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 600µs (77+523) within Template::Context::localise which was called 4 times, avg 150µs/call:
# 4 times (77µs+523µs) by Template::Service::process at line 78 of Template/Service.pm, avg 150µs/call | ||||
| 566 | 1 | 500ns | my $self = shift; | ||
| 567 | 1 | 9µs | 4 | 523µs | $self->{ STASH } = $self->{ STASH }->clone(@_); # spent 523µs making 4 calls to Template::Stash::clone, avg 131µs/call |
| 568 | } | ||||
| 569 | |||||
| 570 | # spent 26µs (21+4) within Template::Context::delocalise which was called 4 times, avg 6µs/call:
# 4 times (21µs+4µs) by Template::Service::process at line 124 of Template/Service.pm, avg 6µs/call | ||||
| 571 | 1 | 300ns | my $self = shift; | ||
| 572 | 1 | 4µs | 4 | 4µs | $self->{ STASH } = $self->{ STASH }->declone(); # spent 4µs making 4 calls to Template::Stash::declone, avg 1µs/call |
| 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 128µs within Template::Context::visit which was called 40 times, avg 3µs/call:
# 40 times (128µs+0s) by Template::Document::process at line 158 of Template/Document.pm, avg 3µs/call | ||||
| 588 | 10 | 4µs | my ($self, $document, $blocks) = @_; | ||
| 589 | 10 | 38µs | 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 92µs within Template::Context::leave which was called 40 times, avg 2µs/call:
# 40 times (92µs+0s) by Template::Document::process at line 167 of Template/Document.pm, avg 2µs/call | ||||
| 604 | 10 | 4µs | my $self = shift; | ||
| 605 | 10 | 27µs | 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 | |||||
| 651 | #------------------------------------------------------------------------ | ||||
| 652 | # define_vmethod($type, $name, \&sub) | ||||
| 653 | # | ||||
| 654 | # Passes $type, $name, and &sub on to stash->define_vmethod(). | ||||
| 655 | #------------------------------------------------------------------------ | ||||
| 656 | |||||
| 657 | sub define_vmethod { | ||||
| 658 | my $self = shift; | ||||
| 659 | $self->stash->define_vmethod(@_); | ||||
| 660 | } | ||||
| 661 | |||||
| 662 | |||||
| 663 | #------------------------------------------------------------------------ | ||||
| 664 | # define_view($name, $params) | ||||
| 665 | # | ||||
| 666 | # Defines a new view. | ||||
| 667 | #------------------------------------------------------------------------ | ||||
| 668 | |||||
| 669 | sub define_view { | ||||
| 670 | my ($self, $name, $params) = @_; | ||||
| 671 | my $base; | ||||
| 672 | |||||
| 673 | if (defined $params->{ base }) { | ||||
| 674 | my $base = $self->{ STASH }->get($params->{ base }); | ||||
| 675 | |||||
| 676 | return $self->throw( | ||||
| 677 | &Template::Constants::ERROR_VIEW, | ||||
| 678 | "view base is not defined: $params->{ base }" | ||||
| 679 | ) unless $base; | ||||
| 680 | |||||
| 681 | return $self->throw( | ||||
| 682 | &Template::Constants::ERROR_VIEW, | ||||
| 683 | "view base is not a $VIEW_CLASS object: $params->{ base } => $base" | ||||
| 684 | ) unless blessed($base) && $base->isa($VIEW_CLASS); | ||||
| 685 | |||||
| 686 | $params->{ base } = $base; | ||||
| 687 | } | ||||
| 688 | my $view = $self->view($params); | ||||
| 689 | $view->seal(); | ||||
| 690 | $self->{ STASH }->set($name, $view); | ||||
| 691 | } | ||||
| 692 | |||||
| 693 | |||||
| 694 | #------------------------------------------------------------------------ | ||||
| 695 | # define_views($views) | ||||
| 696 | # | ||||
| 697 | # Defines multiple new views. | ||||
| 698 | #------------------------------------------------------------------------ | ||||
| 699 | |||||
| 700 | sub define_views { | ||||
| 701 | my ($self, $views) = @_; | ||||
| 702 | |||||
| 703 | # a list reference is better because the order is deterministic (and so | ||||
| 704 | # allows an earlier VIEW to be the base for a later VIEW), but we'll | ||||
| 705 | # accept a hash reference and assume that the user knows the order of | ||||
| 706 | # processing is undefined | ||||
| 707 | $views = [ %$views ] | ||||
| 708 | if ref $views eq 'HASH'; | ||||
| 709 | |||||
| 710 | # make of copy so we don't destroy the original list reference | ||||
| 711 | my @items = @$views; | ||||
| 712 | my ($name, $view); | ||||
| 713 | |||||
| 714 | while (@items) { | ||||
| 715 | $self->define_view(splice(@items, 0, 2)); | ||||
| 716 | } | ||||
| 717 | } | ||||
| 718 | |||||
| 719 | |||||
| 720 | #------------------------------------------------------------------------ | ||||
| 721 | # reset() | ||||
| 722 | # | ||||
| 723 | # Reset the state of the internal BLOCKS hash to clear any BLOCK | ||||
| 724 | # definitions imported via the PROCESS directive. Any original | ||||
| 725 | # BLOCKS definitions passed to the constructor will be restored. | ||||
| 726 | #------------------------------------------------------------------------ | ||||
| 727 | |||||
| 728 | # spent 28µs within Template::Context::reset which was called 4 times, avg 7µs/call:
# 4 times (28µs+0s) by Template::Service::process at line 64 of Template/Service.pm, avg 7µs/call | ||||
| 729 | 1 | 400ns | my ($self, $blocks) = @_; | ||
| 730 | 1 | 2µs | $self->{ BLKSTACK } = [ ]; | ||
| 731 | 1 | 5µs | $self->{ BLOCKS } = { %{ $self->{ INIT_BLOCKS } } }; | ||
| 732 | } | ||||
| 733 | |||||
| 734 | |||||
| 735 | #------------------------------------------------------------------------ | ||||
| 736 | # stash() | ||||
| 737 | # | ||||
| 738 | # Simple accessor methods to return the STASH values. This is likely | ||||
| 739 | # to be called quite often so we provide a direct method rather than | ||||
| 740 | # relying on the slower AUTOLOAD. | ||||
| 741 | #------------------------------------------------------------------------ | ||||
| 742 | |||||
| 743 | # spent 88µs within Template::Context::stash which was called 40 times, avg 2µs/call:
# 4 times (11µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc:120] at line 3 of (eval 1135)[Template/Document.pm:78], avg 3µs/call
# 4 times (9µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/intranet-bottom.inc:94] at line 3 of (eval 1138)[Template/Document.pm:78], avg 2µs/call
# 4 times (9µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc:99] at line 3 of (eval 1131)[Template/Document.pm:78], avg 2µs/call
# 4 times (8µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search-box.inc:62] at line 3 of (eval 1137)[Template/Document.pm:78], avg 2µs/call
# 4 times (8µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/intranetstylesheet.inc:28] at line 3 of (eval 1132)[Template/Document.pm:78], avg 2µs/call
# 4 times (8µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-open.inc:36] at line 3 of (eval 1130)[Template/Document.pm:78], avg 2µs/call
# 4 times (8µs+0s) by Template::Document::__ANON__[(eval 1134)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1155)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1171)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1242)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] at line 3 of (eval 1134)[Template/Document.pm:78], avg 2µs/call
# 4 times (6µs+0s) by Template::Document::__ANON__[(eval 1133)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1154)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1170)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] or Template::Document::__ANON__[(eval 1241)[/usr/lib/x86_64-linux-gnu/perl5/5.20/Template/Document.pm:78]:16] at line 3 of (eval 1133)[Template/Document.pm:78], avg 2µs/call
# 3 times (9µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/errors/404.tt:45] at line 3 of (eval 1129)[Template/Document.pm:78], avg 3µs/call
# 3 times (6µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/cat-search.inc:41] at line 3 of (eval 1136)[Template/Document.pm:78], avg 2µs/call
# once (3µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt:203] at line 3 of (eval 1237)[Template/Document.pm:78]
# once (2µs+0s) by Template::Document::__ANON__[/home/vagrant/kohaclone/koha-tmpl/intranet-tmpl/prog/en/includes/home-search.inc:48] at line 3 of (eval 1244)[Template/Document.pm:78] | ||||
| 744 | 10 | 72µs | return $_[0]->{ STASH }; | ||
| 745 | } | ||||
| 746 | |||||
| 747 | |||||
| 748 | #------------------------------------------------------------------------ | ||||
| 749 | # debugging($command, @args, \%params) | ||||
| 750 | # | ||||
| 751 | # Method for controlling the debugging status of the context. The first | ||||
| 752 | # argument can be 'on' or 'off' to enable/disable debugging, 'format' | ||||
| 753 | # to define the format of the debug message, or 'msg' to generate a | ||||
| 754 | # debugging message reporting the file, line, message text, etc., | ||||
| 755 | # according to the current debug format. | ||||
| 756 | #------------------------------------------------------------------------ | ||||
| 757 | |||||
| 758 | sub debugging { | ||||
| 759 | my $self = shift; | ||||
| 760 | my $hash = ref $_[-1] eq 'HASH' ? pop : { }; | ||||
| 761 | my @args = @_; | ||||
| 762 | |||||
| 763 | if (@args) { | ||||
| 764 | if ($args[0] =~ /^on|1$/i) { | ||||
| 765 | $self->{ DEBUG_DIRS } = 1; | ||||
| 766 | shift(@args); | ||||
| 767 | } | ||||
| 768 | elsif ($args[0] =~ /^off|0$/i) { | ||||
| 769 | $self->{ DEBUG_DIRS } = 0; | ||||
| 770 | shift(@args); | ||||
| 771 | } | ||||
| 772 | } | ||||
| 773 | |||||
| 774 | if (@args) { | ||||
| 775 | if ($args[0] =~ /^msg$/i) { | ||||
| 776 | return unless $self->{ DEBUG_DIRS }; | ||||
| 777 | my $format = $self->{ DEBUG_FORMAT }; | ||||
| 778 | $format = $DEBUG_FORMAT unless defined $format; | ||||
| 779 | $format =~ s/\$(\w+)/$hash->{ $1 }/ge; | ||||
| 780 | return $format; | ||||
| 781 | } | ||||
| 782 | elsif ($args[0] =~ /^format$/i) { | ||||
| 783 | $self->{ DEBUG_FORMAT } = $args[1]; | ||||
| 784 | } | ||||
| 785 | # else ignore | ||||
| 786 | } | ||||
| 787 | |||||
| 788 | return ''; | ||||
| 789 | } | ||||
| 790 | |||||
| 791 | |||||
| 792 | #------------------------------------------------------------------------ | ||||
| 793 | # AUTOLOAD | ||||
| 794 | # | ||||
| 795 | # Provides pseudo-methods for read-only access to various internal | ||||
| 796 | # members. For example, templates(), plugins(), filters(), | ||||
| 797 | # eval_perl(), load_perl(), etc. These aren't called very often, or | ||||
| 798 | # may never be called at all. | ||||
| 799 | #------------------------------------------------------------------------ | ||||
| 800 | |||||
| 801 | sub AUTOLOAD { | ||||
| 802 | my $self = shift; | ||||
| 803 | my $method = $AUTOLOAD; | ||||
| 804 | my $result; | ||||
| 805 | |||||
| 806 | $method =~ s/.*:://; | ||||
| 807 | return if $method eq 'DESTROY'; | ||||
| 808 | |||||
| 809 | warn "no such context method/member: $method\n" | ||||
| 810 | unless defined ($result = $self->{ uc $method }); | ||||
| 811 | |||||
| 812 | return $result; | ||||
| 813 | } | ||||
| 814 | |||||
| 815 | |||||
| 816 | #------------------------------------------------------------------------ | ||||
| 817 | # DESTROY | ||||
| 818 | # | ||||
| 819 | # Stash may contain references back to the Context via macro closures, | ||||
| 820 | # etc. This breaks the circular references. | ||||
| 821 | #------------------------------------------------------------------------ | ||||
| 822 | |||||
| 823 | # spent 18µs within Template::Context::DESTROY which was called 4 times, avg 4µs/call:
# 3 times (14µs+0s) by CGI::Compile::ROOT::home_vagrant_kohaclone_errors_404_2epl::__ANON__[/home/vagrant/kohaclone/errors/404.pl:58] at line 2 of errors/404.pl, avg 5µs/call
# once (4µs+0s) by CGI::Compile::ROOT::home_vagrant_kohaclone_mainpage_2epl::__ANON__[/home/vagrant/kohaclone/mainpage.pl:107] at line 2 of mainpage.pl | ||||
| 824 | 1 | 500ns | my $self = shift; | ||
| 825 | 1 | 6µs | undef $self->{ STASH }; | ||
| 826 | } | ||||
| 827 | |||||
| - - | |||||
| 830 | #======================================================================== | ||||
| 831 | # -- PRIVATE METHODS -- | ||||
| 832 | #======================================================================== | ||||
| 833 | |||||
| 834 | #------------------------------------------------------------------------ | ||||
| 835 | # _init(\%config) | ||||
| 836 | # | ||||
| 837 | # Initialisation method called by Template::Base::new() | ||||
| 838 | #------------------------------------------------------------------------ | ||||
| 839 | |||||
| 840 | # spent 16.3ms (273µs+16.0) within Template::Context::_init which was called 4 times, avg 4.07ms/call:
# 4 times (273µs+16.0ms) by Template::Base::new at line 65 of Template/Base.pm, avg 4.07ms/call | ||||
| 841 | 1 | 500ns | my ($self, $config) = @_; | ||
| 842 | 1 | 300ns | my ($name, $item, $method, $block, $blocks); | ||
| 843 | 1 | 3µs | my @itemlut = ( | ||
| 844 | LOAD_TEMPLATES => 'provider', | ||||
| 845 | LOAD_PLUGINS => 'plugins', | ||||
| 846 | LOAD_FILTERS => 'filters' | ||||
| 847 | ); | ||||
| 848 | |||||
| 849 | # LOAD_TEMPLATE, LOAD_PLUGINS, LOAD_FILTERS - lists of providers | ||||
| 850 | 1 | 2µs | while (($name, $method) = splice(@itemlut, 0, 2)) { | ||
| 851 | 3 | 12µs | 12 | 5.52ms | $item = $config->{ $name } # spent 3.57ms making 4 calls to Template::Config::filters, avg 893µs/call
# spent 1.64ms making 4 calls to Template::Config::plugins, avg 410µs/call
# spent 310µs making 4 calls to Template::Config::provider, avg 78µs/call |
| 852 | || Template::Config->$method($config) | ||||
| 853 | || return $self->error($Template::Config::ERROR); | ||||
| 854 | 3 | 10µs | $self->{ $name } = ref $item eq 'ARRAY' ? $item : [ $item ]; | ||
| 855 | } | ||||
| 856 | |||||
| 857 | 1 | 500ns | my $providers = $self->{ LOAD_TEMPLATES }; | ||
| 858 | 1 | 3µs | my $prefix_map = $self->{ PREFIX_MAP } = $config->{ PREFIX_MAP } || { }; | ||
| 859 | 1 | 2µs | while (my ($key, $val) = each %$prefix_map) { | ||
| 860 | $prefix_map->{ $key } = [ ref $val ? $val : | ||||
| 861 | map { $providers->[$_] } split(/\D+/, $val) ] | ||||
| 862 | unless ref $val eq 'ARRAY'; | ||||
| 863 | } | ||||
| 864 | |||||
| 865 | # STASH | ||||
| 866 | 1 | 2µs | $self->{ STASH } = $config->{ STASH } || do { | ||
| 867 | my $predefs = $config->{ VARIABLES } | ||||
| 868 | || $config->{ PRE_DEFINE } | ||||
| 869 | 1 | 1µs | || { }; | ||
| 870 | |||||
| 871 | # hack to get stash to know about debug mode | ||||
| 872 | $predefs->{ _DEBUG } = ( ($config->{ DEBUG } || 0) | ||||
| 873 | & &Template::Constants::DEBUG_UNDEF ) ? 1 : 0 | ||||
| 874 | 1 | 7µs | 4 | 6µs | unless defined $predefs->{ _DEBUG }; # spent 6µs making 4 calls to Template::Constants::DEBUG_UNDEF, avg 2µs/call |
| 875 | 1 | 2µs | $predefs->{ _STRICT } = $config->{ STRICT }; | ||
| 876 | |||||
| 877 | 1 | 3µs | 4 | 10.5ms | Template::Config->stash($predefs) # spent 10.5ms making 4 calls to Template::Config::stash, avg 2.62ms/call |
| 878 | || return $self->error($Template::Config::ERROR); | ||||
| 879 | }; | ||||
| 880 | |||||
| 881 | # compile any template BLOCKS specified as text | ||||
| 882 | 1 | 600ns | $blocks = $config->{ BLOCKS } || { }; | ||
| 883 | $self->{ INIT_BLOCKS } = $self->{ BLOCKS } = { | ||||
| 884 | map { | ||||
| 885 | 1 | 3µs | $block = $blocks->{ $_ }; | ||
| 886 | $block = $self->template(\$block) | ||||
| 887 | || return undef | ||||
| 888 | unless ref $block; | ||||
| 889 | ($_ => $block); | ||||
| 890 | } | ||||
| 891 | keys %$blocks | ||||
| 892 | }; | ||||
| 893 | |||||
| 894 | # define any VIEWS | ||||
| 895 | $self->define_views( $config->{ VIEWS } ) | ||||
| 896 | 1 | 300ns | if $config->{ VIEWS }; | ||
| 897 | |||||
| 898 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | ||||
| 899 | # RECURSION - flag indicating is recursion into templates is supported | ||||
| 900 | # EVAL_PERL - flag indicating if PERL blocks should be processed | ||||
| 901 | # TRIM - flag to remove leading and trailing whitespace from output | ||||
| 902 | # BLKSTACK - list of hashes of BLOCKs defined in current template(s) | ||||
| 903 | # CONFIG - original configuration hash | ||||
| 904 | # EXPOSE_BLOCKS - make blocks visible as pseudo-files | ||||
| 905 | # DEBUG_FORMAT - format for generating template runtime debugging messages | ||||
| 906 | # DEBUG - format for generating template runtime debugging messages | ||||
| 907 | |||||
| 908 | 1 | 2µs | $self->{ RECURSION } = $config->{ RECURSION } || 0; | ||
| 909 | 1 | 500ns | $self->{ EVAL_PERL } = $config->{ EVAL_PERL } || 0; | ||
| 910 | 1 | 700ns | $self->{ TRIM } = $config->{ TRIM } || 0; | ||
| 911 | 1 | 700ns | $self->{ BLKSTACK } = [ ]; | ||
| 912 | 1 | 400ns | $self->{ CONFIG } = $config; | ||
| 913 | $self->{ EXPOSE_BLOCKS } = defined $config->{ EXPOSE_BLOCKS } | ||||
| 914 | ? $config->{ EXPOSE_BLOCKS } | ||||
| 915 | 1 | 600ns | : 0; | ||
| 916 | |||||
| 917 | 1 | 1µs | $self->{ DEBUG_FORMAT } = $config->{ DEBUG_FORMAT }; | ||
| 918 | 1 | 2µs | $self->{ DEBUG_DIRS } = ($config->{ DEBUG } || 0) | ||
| 919 | & Template::Constants::DEBUG_DIRS; | ||||
| 920 | $self->{ DEBUG } = defined $config->{ DEBUG } | ||||
| 921 | 1 | 1µs | ? $config->{ DEBUG } & ( Template::Constants::DEBUG_CONTEXT | ||
| 922 | | Template::Constants::DEBUG_FLAGS ) | ||||
| 923 | : $DEBUG; | ||||
| 924 | |||||
| 925 | 1 | 3µs | return $self; | ||
| 926 | } | ||||
| 927 | |||||
| 928 | |||||
| 929 | #------------------------------------------------------------------------ | ||||
| 930 | # _dump() | ||||
| 931 | # | ||||
| 932 | # Debug method which returns a string representing the internal state | ||||
| 933 | # of the context object. | ||||
| 934 | #------------------------------------------------------------------------ | ||||
| 935 | |||||
| 936 | sub _dump { | ||||
| 937 | my $self = shift; | ||||
| 938 | my $output = "[Template::Context] {\n"; | ||||
| 939 | my $format = " %-16s => %s\n"; | ||||
| 940 | my $key; | ||||
| 941 | |||||
| 942 | foreach $key (qw( RECURSION EVAL_PERL TRIM )) { | ||||
| 943 | $output .= sprintf($format, $key, $self->{ $key }); | ||||
| 944 | } | ||||
| 945 | foreach my $pname (qw( LOAD_TEMPLATES LOAD_PLUGINS LOAD_FILTERS )) { | ||||
| 946 | my $provtext = "[\n"; | ||||
| 947 | foreach my $prov (@{ $self->{ $pname } }) { | ||||
| 948 | $provtext .= $prov->_dump(); | ||||
| 949 | # $provtext .= ",\n"; | ||||
| 950 | } | ||||
| 951 | $provtext =~ s/\n/\n /g; | ||||
| 952 | $provtext =~ s/\s+$//; | ||||
| 953 | $provtext .= ",\n ]"; | ||||
| 954 | $output .= sprintf($format, $pname, $provtext); | ||||
| 955 | } | ||||
| 956 | $output .= sprintf($format, STASH => $self->{ STASH }->_dump()); | ||||
| 957 | $output .= '}'; | ||||
| 958 | return $output; | ||||
| 959 | } | ||||
| 960 | |||||
| 961 | |||||
| 962 | 1; | ||||
| 963 | |||||
| 964 | __END__ | ||||
# spent 84µs within Template::Context::CORE:subst which was called 40 times, avg 2µs/call:
# 40 times (84µs+0s) by Template::Context::template at line 116, avg 2µs/call |