/usr/local/CPAN/Apache-Voodoo/Apache/Voodoo/View/HTML.pm
################################################################################
#
# Apache::Voodoo::View::HTML
#
# This modules is used internally by Voodoo for interfacing to HTML::Template.
#
################################################################################
package Apache::Voodoo::View::HTML;
$VERSION = "3.0200";
use strict;
use warnings;
use File::Spec;
use HTML::Template;
use Apache::Voodoo::Exception;
use Exception::Class::DBI;
use base ("Apache::Voodoo::View");
sub init {
my $self = shift;
my $config = shift;
$self->{'template_dir'} = $config->{'template_dir'};
$self->{'template_opts'} = $config->{'template_opts'};
$self->{'template_opts'}->{'die_on_bad_params'} = 0;
$self->{'template_opts'}->{'global_vars'} = 1;
$self->{'template_opts'}->{'loop_context_vars'} = 1;
$self->{'template_opts'}->{'path'} = [ $config->{'template_dir'} ];
$self->{'site_root'} = $config->{'site_root'};
$self->{'use_themes'} = $config->{'themes'}->{'use_themes'};
if ($self->{'use_themes'}) {
require Apache::Voodoo::View::HTML::Theme;
$self->{'theme_handler'} = Apache::Voodoo::View::HTML::Theme->new($config->{'themes'});
}
$self->content_type('text/html');
}
sub begin {
my $self = shift;
my $p = shift;
$self->content_type($p->{"template_conf"}->{"content-type"} || 'text/html');
my $skeleton;
eval {
my $return;
if ($self->{'use_themes'}) {
# time to do the theme processing stuff.
$return = $self->{'theme_handler'}->handle(
{
"document_root" => $self->{'template_dir'},
"session" => $p->{'session'},
"uri" => $p->{'uri'},
}
);
$skeleton = $self->{'theme_handler'}->get_skeleton();
}
else {
$skeleton = $p->{'template_conf'}->{'skeleton'} || 'skeleton';
}
$self->_load_skeleton($skeleton);
$self->_load_template($p->{'uri'});
$self->params(SITE_ROOT => $self->{site_root});
$self->params($return) if ($return);
};
if ($@) {
$self->_internal_error($@);
}
}
sub _load_skeleton {
my $self = shift;
my $s = shift;
$self->{skeleton_template} = HTML::Template->new(
'filename' => File::Spec->catfile($self->{'template_dir'},$s.".tmpl"),
%{$self->{'template_opts'}}
);
}
sub _load_template {
my $self = shift;
my $u = shift;
$self->{template} = HTML::Template->new(
'filename' => File::Spec->catfile($self->{'template_dir'},$u.".tmpl"),
%{$self->{'template_opts'}}
);
}
sub _load_internal_template {
my $self = shift;
my $u = shift;
my $path = $INC{'Apache/Voodoo/View/HTML.pm'};
$path =~ s/\.pm/\//o;
$self->{template} = HTML::Template->new(
'filename' => $path.$u.'.tmpl',
%{$self->{'template_opts'}}
);
}
sub params {
my $self = shift;
return if ($self->{internal_error});
eval {
$self->{skeleton_template}->param(@_);
$self->{template}->param(@_);
};
if ($@) {
$self->_internal_error($@);
}
}
sub exception {
my $self = shift;
my $e = shift;
return if ($self->{internal_error});
eval {
if ($e->isa("Exception::Class::DBI")) {
$self->_load_internal_template("db_error");
$self->params(
"description" => "Database Error",
"message" => $e->errstr,
"package" => $e->package,
"line" => $e->line,
"query" => $self->_format_query($e->statement)
);
}
elsif ($e->isa("Apache::Voodoo::Exception::Application::DisplayError")) {
if (-e File::Spec->catfile($self->{'template_dir'},"display_error.tmpl")) {
$self->_load_template("display_error");
}
else {
$self->_load_internal_template("display_error");
}
$self->params('error_url' => $e->target);
if (ref($e->error) eq "HASH") {
$self->params($e->error);
}
else {
$self->params('error_string' => $e->error);
}
}
elsif ($e->isa("Apache::Voodoo::Exception")) {
$self->_load_internal_template("exception");
$self->params(
"description" => $e->description,
"message" => $e->error
);
if ($e->isa("Apache::Voodoo::Exception::RunTime")) {
$self->params("stack" => Apache::Voodoo::Exception::parse_stack_trace($e->trace()));
}
}
else {
$self->_load_internal_template("exception");
$self->params("message" => "$e");
}
};
if ($@) {
$self->_internal_error($@);
}
}
sub output {
my $self = shift;
if ($self->{internal_error}) {
return
"<html><body>".
"<h2>The following error was encountered while processing this request:</h2>".
"<pre>".$self->{error_msg}."</pre>".
"</body></html>";
}
else {
$self->{skeleton_template}->param('_MAIN_BODY_' => $self->{template}->output());
return $self->{skeleton_template}->output();
}
}
sub finish {
my $self = shift;
$self->{template} = undef;
$self->{skeletong_template} = undef;
$self->{internal_error} = 0;
$self->{error_msg} = undef;
}
sub _internal_error {
my $self = shift;
$self->content_type("text/html");
$self->{internal_error} = 1;
$self->{error_msg} = shift;
}
sub _format_query {
my $self = shift;
my $query = shift;
my $leading = undef;
my @lines;
foreach my $line (split(/\n/,$query)) {
$line =~ s/[\r\n]//g;
$line =~ s/(?<![ \S])\t/ /g; # negative look-behind assertion. replaces only leading tabs
if (!defined($leading)) {
next if $line =~ /^\s*$/;
my $l = $line;
$l =~ s/\S.*$//;
if (length($l)) {
$leading = length($l);
}
}
else {
my $l = $line;
$l =~ s/\S.*$//;
if (length($l) and length($l) < $leading) {
$leading = length($l);
}
}
push (@lines,$line);
}
return join(
"\n",
map {
$_ =~ s/^ {$leading}//;
$_;
} @lines
);
}
1;
################################################################################
# Copyright (c) 2005-2010 Steven Edwards (maverick@smurfbane.org).
# All rights reserved.
#
# You may use and distribute Apache::Voodoo under the terms described in the
# LICENSE file include in this package. The summary is it's a legalese version
# of the Artistic License :)
#
################################################################################