package Anvil::Tools::Template; # # This module contains methods used to handle templates. # use strict; use warnings; use Data::Dumper; use Scalar::Util qw(weaken isweak); our $VERSION = "3.0.0"; my $THIS_FILE = "Template.pm"; ### Methods; # get # select_form # skin =pod =encoding utf8 =head1 NAME Anvil::Tools::Template Provides all methods related to template handling. =head1 SYNOPSIS use Anvil::Tools; # Template a common object handle on all Anvil::Tools modules. my $anvil = Anvil::Tools->new(); # Access to methods using '$anvil->Template->X'. # # Example using '()'; =head1 METHODS Methods in this module; =cut sub new { my $class = shift; my $self = { SKIN => { HTML => "", }, }; bless $self, $class; return ($self); } # Get a handle on the Anvil::Tools object. I know that technically that is a sibling module, but it makes more # sense in this case to think of it as a parent. sub parent { my $self = shift; my $parent = shift; $self->{HANDLE}{TOOLS} = $parent if $parent; # Defend against memory leads. See Scalar::Util'. if (not isweak($self->{HANDLE}{TOOLS})) { weaken($self->{HANDLE}{TOOLS});; } return ($self->{HANDLE}{TOOLS}); } ############################################################################################################# # Public methods # ############################################################################################################# =head2 get This method takes a template file name and a template section name and returns that body template. my $body = $anvil->Template->get({file => "foo.html", name => "bar"})) =head2 Parameters; =head3 file (required) This is the name of the template file containing the template section you want to read. =head3 language (optional) This is the language (iso code) to use when inserting strings into the template. When not specified, 'C<< Words->language >>' is used. =head3 name (required) This is the name of the template section, bounded by 'C<< >>' and 'C<< >>' to read in from the file. =head3 show_name (optional) If set the C<< 1 >>, the HTML will have comments shows which parts came from what file. By default, this is disabled. =head3 skin (optional) By default, the active skin is set by 'C<< defaults::template::html >>' ('C<< alteeve >>' by default). This can be checked or set using 'C<< Template->skin >>'. This parameter allows for an override to use another skin. =head3 variables (optional) If there are variables to inject into the template, pass them as a hash referencce using this paramter. =cut sub get { my $self = shift; my $parameter = shift; my $anvil = $self->parent; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $test = defined $parameter->{test} ? $parameter->{test} : 0; my $file = defined $parameter->{file} ? $parameter->{file} : ""; my $language = defined $parameter->{language} ? $parameter->{language} : $anvil->Words->language({debug => $debug}); my $name = defined $parameter->{name} ? $parameter->{name} : ""; my $show_name = defined $parameter->{show_name} ? $parameter->{show_name} : 1; my $skin = defined $parameter->{skin} ? $parameter->{skin} : $anvil->Template->skin({debug => $debug}); my $variables = defined $parameter->{variables} ? $parameter->{variables} : ""; $skin = $anvil->data->{path}{directories}{skins}."/".$skin; my $template = ""; my $source = ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file => $file, language => $language, name => $name, skin => $skin, variables => ref($variables) ? ref($variables) : $variables, }}); if (($anvil->Log->level >= $debug) && (ref($variables) eq "HASH")) { foreach my $key (sort {$a cmp $b} keys %{$variables}) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "variables->{$key}" => $variables->{$key} }}); } } # The 'http_headers' template can never show the name $show_name = 0 if $name eq "http_headers"; my $error = 0; if (not $file) { # No file passed. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0024"}); $error = 1; } else { # Make sure the file exists. if ($file =~ /^\//) { # Fully defined path, don't alter it. $source = $file; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { source => $source }}); } else { # Just a file name, prepend the skin path. $source = $skin."/".$file; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { source => $source }}); } if (not -e $source) { # Source doesn't exist $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0025", variables => { source => $source }}); $error = 1; } elsif (not -r $source) { # Source isn't readable. my $user_name = getpwuid($<); $user_name = $< if not $user_name; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0026", variables => { source => $source, user_name => $user_name }}); $error = 1; } } if (not $name) { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0027"}); $error = 1; } if (not $error) { my $template_found = 0; my $in_template = 0; my $template_file = $anvil->Storage->read_file({debug => $debug, file => $source}); foreach my $line (split/\n/, $template_file) { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0023", variables => { line => $line }}); if ($line =~ /^/) { $in_template = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_template => $in_template }}); if ($show_name) { $template .= "\n"; } next; } if ($in_template) { if ($line =~ /^/) { $in_template = 0; $template_found = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { in_template => $in_template, template_found => $template_found, }}); if ($show_name) { $template .= "\n"; } last; } else { $template .= $line."\n"; } } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { template => $template }}); # Insert variables if I found something. # Now that I have the skin, inject my variables. We'll use Words->string() to do this for us. if (($template_found) && ($template)) { $template = $anvil->Words->string({ string => $template, variables => $variables, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { template => $template }}); } # If we failed to read the template, then load an error message. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { template_found => $template_found, template => $template, }}); if ((not $template_found) or ($template eq "#!not_found!#")) { # Woops! $template = $anvil->Words->string({key => "error_0029", variables => { template => $name, file => $source, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { template => $template }}); } # If there was a problem processing the template, it will be '#!error!#'. if ($template eq "#!error!#") { $template = $anvil->Words->string({key => "error_0030", variables => { template => $name, file => $source, }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { template => $template }}); return($template); } =head2 select_form This builds a \n"; if ($class) { $select = "\n"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'select' => $select }}); return($select); } =head2 skin This sets or returns the active skin used when rendering web output. The default skin is set via 'C<< defaults::template::html >>' and it must be the same as the directory name under 'C<< /var/www/html/skins/ >>'. Get the active skin directory; my $skin = $anvil->Template->skin; Set the active skin to 'C<< foo >>'. Only pass the skin name, not the full path. $anvil->Template->skin({set => "foo"}); Parameters; =head3 fatal (optional) If passed along with C<< set >>, the skin will be set even if the skin directory does not exit. =head3 set (optional) If passed a string, that will become the new active skin. If the skin directory does not exist, however, and C<< fatal >> is not set, the request will be ignored. =cut sub skin { my $self = shift; my $parameter = shift; my $anvil = $self->parent; my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; my $fatal = defined $parameter->{fatal} ? $parameter->{fatal} : 1; my $set = defined $parameter->{set} ? $parameter->{set} : ""; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { fatal => $fatal, set => $set }}); if ($set) { my $skin_directory = $anvil->data->{path}{directories}{skins}."/".$set; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { skin_directory => $skin_directory }}); if ((-d $skin_directory) or (not $fatal)) { $self->{SKIN}{HTML} = $set; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'SKIN::HTML' => $self->{SKIN}{HTML} }}); } else { $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0031", variables => { set => $set, skin_directory => $skin_directory }}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'SKIN::HTML' => $self->{SKIN}{HTML} }}); if (not $self->{SKIN}{HTML}) { $self->{SKIN}{HTML} = $anvil->data->{defaults}{template}{html}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'SKIN::HTML' => $self->{SKIN}{HTML}, 'defaults::template::html' => $anvil->data->{defaults}{template}{html} }}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { 'SKIN::HTML' => $self->{SKIN}{HTML} }}); return($self->{SKIN}{HTML}); } # =head3 # # Private Functions; # # =cut ############################################################################################################# # Private functions # ############################################################################################################# 1;