Apache2-Controller
view release on metacpan or search on metacpan
lib/Apache2/Controller/Render/Template.pm view on Meta::CPAN
;
a2cx message => "$type error - $info",
status => $status_code,
status_line => "$status_code $type error - $info",
;
}
$self->print($output);
return;
}
=head2 render_fast
So if you are planning to get a large
data set, you probably want to use $self->render_fast()
and put the database query handle somewhere in $self->{stash}
and call fetchrow() in a Template block.
With render_fast(), Template->process() outputs directly to
Apache2::Request->print(). So if a Template error is encountered,
some output may have already been sent to the browser, resulting
in a completely screwed up screen when the exception is kicked
back up to the server.
Tip: if you plan to use render_fast(), write a test suite that
tests the output of your page.
Of course you could bypass rendering altogether and just use
$self->print(). (Remember that $self is
normally subclassed in L<Apache2::Request> which magically
delegates to C<< $self->{r} >>.)
Or maybe you should implement an ajax style control in the template
and put a limit frame on the query above, or use a paging lib, etc. ...
=cut
sub render_fast {
my ($self) = @_;
$self->pnotes->{a2c}{use_standard_errors} = 1;
my $template = $self->detect_template();
DEBUG("processing template = '$template'");
# DEBUG(sub { Dump($self->{stash}) });
$self->_assign_tt_stash_data();
my $tt = $self->get_tt_obj();
# pass Apache2::Request object to print directly.
$tt->process($template, $self->{stash}, $self->{r}) || a2cx $tt->error();
return;
}
=head2 error
If your template directory contains a subdirectory named 'error',
then when the controller throws an exception, the exception object will
be passed to a selected error template as 'X' in the stash. It also
sets status (number) and status_line
(from HTTP::Status::status_message() or from the values
set in the L<Apache2::Controller::X> exception).
If you have a template $template_dir/error/$status.html,
where $status is the numeric http status code,
then it will use that template.
For example:
203 HTTP_NON_AUTHORITATIVE => error/203.html
400 HTTP_BAD_REQUEST => error/400.html
404 NOT_FOUND => error/404.html
500 HTTP_INTERNAL_SERVER_ERROR => error/500.html
For example, C<$template_dir/error/400.html> or
C<$template_dir/error/403.html>.
Otherwise it will look for $template_dir/error/default.html and
try to use that, otherwise it will give up.
error() remembers across requests whether you do or don't have
error templates for certain messages in the appropriate template directory,
so it will be faster the second time around if you use error/default.html.
For a reference list of status and messages, see Apache2::Controller.
Since render_fast() is incompatible if a template rendering error
occurs, render_fast() turns off the use of error() and relies on
standard Apache2 error messages (or the custom message set in
the exception object) and relies on the browser to display them.
=cut
my %error_templates = ( );
sub error {
my ($self, $X) = @_;
my ($status, $status_line);
DEBUG("original error: '$X'");
if (ref($X) && $X->isa('Apache2::Controller::X')) {
$status = $X->status;
$status_line = $X->status_line;
DEBUG("got status from \$X: ".($status || '[none]'));
}
$status ||= Apache2::Const::SERVER_ERROR;
$status_line ||= $status.' '.status_message($status);
my $status_file = $status;
DEBUG("status msg for $status_file: '$status_line'");
$self->{stash}{X} = $X;
$self->{stash}{status_line} = $status_line;
$self->{stash}{status} = $status;
my $template_dir = $self->get_directive('A2C_Render_Template_Path')
|| a2cx 'A2C_Render_Template_Path not defined.';
DEBUG sub { "A2C_Render_Template_Path:\n".Dump($template_dir) };
if (exists $error_templates{$template_dir}{$status_file}) {
my $template = $error_templates{$template_dir}{$status_file};
# if exists but undefined, it means it failed totally.
# forget about using an error template and just rethrow the error
if (!defined $template) {
if (ref($X) && $X->isa('Apache2::Controller::X')) {
$X->rethrow();
}
else {
a2cx "Cannot process any template for unknown-type error: $X";
}
}
$self->{template} = $template;
$self->render();
}
else {
# does the error directory even exist?
# first try the appropriately named file:
my %try_errors = ( );
$self->{template} = "errors/$status_file.html";
eval { $self->render() };
# if got an error using that file name, try the default error file:
if ($EVAL_ERROR) {
$try_errors{$self->{template}} = "$EVAL_ERROR";
$self->{template} = "errors/default.html";
eval { $self->render() };
# and if error template doesn't work, throw back original error
if ($EVAL_ERROR) {
DEBUG "Error rendering error file: $EVAL_ERROR";
$try_errors{$self->{template}} = "$EVAL_ERROR";
$error_templates{$template_dir}{$status_file} = undef;
if (ref $X && $X->isa('Apache2::Controller::X')) {
$X->rethrow();
}
else {
my $dump = { tries => \%try_errors, reftype => ref $X };
a2cx message => "$X",
status => $status,
status_line => $status_line,
'dump' => $dump;
}
}
}
# after finding the right template for code, remember it for next time
$error_templates{$template_dir}{$status_file} = $self->{template};
}
return;
}
=head2 detect_template
This is called internally by the render methods, but you can use
it to figure out the default template from where you are.
To override the auto-select template, just set $self->{template}
before you call C<<render()>>.
It looks for templates in a computed directory. The directory where it
looks will always be the directory set with the A2C_Render_Template_Path
directive in the config file, appended with the current request location,
i.e. the directory of the Location directive in the config file,
appended with relative_uri, appended with method name and '.html'.
A2C_Render_Template_Path + location + relative_uri + method.html
For example, the sequence in SYNOPSIS above renders the file
C</var/myapp/templates/foo/default.html> .
Suppose the dispatch class above dispatches sub-path uris starting
with 'bar/biz' to another controller. That controller would look for
templates in the directory /var/myapp/templates/foo/bar/biz/methodname.html.
Example:
Request: http://myserver.xyz/foo/bar/biz/baz/boz/noz
location = /foo
relative_uri = bar/biz
controller MyApp::C::Foo::Bar::Biz # mapped in your A2C Dispatch
found method = baz
path_args = [ boz, noz ]
template = /var/myapp/templates + /foo + /bar/biz + /baz.html
/var/myapp/templates/foo/bar/biz/baz.html
$self->{relative_uri} is the uri relative to the location,
so in other words:
( run in 1.510 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )