X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FView%2FTT.pm;h=7277ddfe476696f926708bde853fdcbeb19eb275;hb=ebba23fa2daefd50ccfbb53fcba3f68a5c5d132e;hp=3a3b0253be6b1a04d9eaddfadf9f60aaf186daee;hpb=ae03576773fe6d95b1702b6fede55470994880cc;p=catagits%2FCatalyst-View-TT.git diff --git a/lib/Catalyst/View/TT.pm b/lib/Catalyst/View/TT.pm index 3a3b025..7277ddf 100644 --- a/lib/Catalyst/View/TT.pm +++ b/lib/Catalyst/View/TT.pm @@ -1,69 +1,272 @@ package Catalyst::View::TT; use strict; +use warnings; + use base qw/Catalyst::View/; +use Data::Dump 'dump'; use Template; use Template::Timer; -use NEXT; +use MRO::Compat; -our $VERSION = '0.21'; +our $VERSION = '0.32'; __PACKAGE__->mk_accessors('template'); __PACKAGE__->mk_accessors('include_path'); +*paths = \&include_path; + =head1 NAME Catalyst::View::TT - Template View Class =head1 SYNOPSIS -# use the helper to create View +# use the helper to create your View + myapp_create.pl view TT TT -# configure in lib/MyApp.pm +# configure in lib/MyApp.pm (Could be set from configfile instead) MyApp->config( name => 'MyApp', - root => MyApp->path_to('root');, + root => MyApp->path_to('root'), 'View::TT' => { # any TT configurations items go here INCLUDE_PATH => [ - MyApp->path_to( 'root', 'src' ), - MyApp->path_to( 'root', 'lib' ), + MyApp->path_to( 'root', 'src' ), + MyApp->path_to( 'root', 'lib' ), ], + TEMPLATE_EXTENSION => '.tt', + CATALYST_VAR => 'c', + TIMER => 0, + # Not set by default PRE_PROCESS => 'config/main', WRAPPER => 'site/wrapper', - TEMPLATE_EXTENSION => '.tt', - - # two optional config items - CATALYST_VAR => 'Catalyst', - TIMER => 1, }, ); - -# render view from lib/MyApp.pm or lib/MyApp::C::SomeController.pm - + +# render view from lib/MyApp.pm or lib/MyApp::Controller::SomeController.pm + sub message : Global { my ( $self, $c ) = @_; $c->stash->{template} = 'message.tt2'; $c->stash->{message} = 'Hello World!'; - $c->forward('MyApp::V::TT'); + $c->forward( $c->view('TT') ); } # access variables from template The message is: [% message %]. - + # example when CATALYST_VAR is set to 'Catalyst' - Context is [% Catalyst %] - The base is [% Catalyst.req.base %] - The name is [% Catalyst.config.name %] - + Context is [% Catalyst %] + The base is [% Catalyst.req.base %] + The name is [% Catalyst.config.name %] + # example when CATALYST_VAR isn't set Context is [% c %] The base is [% base %] The name is [% name %] +=cut + +sub _coerce_paths { + my ( $paths, $dlim ) = shift; + return () if ( !$paths ); + return @{$paths} if ( ref $paths eq 'ARRAY' ); + + # tweak delim to ignore C:/ + unless ( defined $dlim ) { + $dlim = ( $^O eq 'MSWin32' ) ? ':(?!\\/)' : ':'; + } + return split( /$dlim/, $paths ); +} + +sub new { + my ( $class, $c, $arguments ) = @_; + my $config = { + EVAL_PERL => 0, + TEMPLATE_EXTENSION => '', + %{ $class->config }, + %{$arguments}, + }; + if ( ! (ref $config->{INCLUDE_PATH} eq 'ARRAY') ) { + my $delim = $config->{DELIMITER}; + my @include_path + = _coerce_paths( $config->{INCLUDE_PATH}, $delim ); + if ( !@include_path ) { + my $root = $c->config->{root}; + my $base = Path::Class::dir( $root, 'base' ); + @include_path = ( "$root", "$base" ); + } + $config->{INCLUDE_PATH} = \@include_path; + } + + # if we're debugging and/or the TIMER option is set, then we install + # Template::Timer as a custom CONTEXT object, but only if we haven't + # already got a custom CONTEXT defined + + if ( $config->{TIMER} ) { + if ( $config->{CONTEXT} ) { + $c->log->error( + 'Cannot use Template::Timer - a TT CONTEXT is already defined' + ); + } + else { + $config->{CONTEXT} = Template::Timer->new(%$config); + } + } + + if ( $c->debug && $config->{DUMP_CONFIG} ) { + $c->log->debug( "TT Config: ", dump($config) ); + } + + my $self = $class->next::method( + $c, { %$config }, + ); + + # Set base include paths. Local'd in render if needed + $self->include_path($config->{INCLUDE_PATH}); + + $self->config($config); + + # Creation of template outside of call to new so that we can pass [ $self ] + # as INCLUDE_PATH config item, which then gets ->paths() called to get list + # of include paths to search for templates. + + # Use a weakend copy of self so we dont have loops preventing GC from working + my $copy = $self; + Scalar::Util::weaken($copy); + $config->{INCLUDE_PATH} = [ sub { $copy->paths } ]; + + if ( $config->{PROVIDERS} ) { + my @providers = (); + if ( ref($config->{PROVIDERS}) eq 'ARRAY') { + foreach my $p (@{$config->{PROVIDERS}}) { + my $pname = $p->{name}; + my $prov = 'Template::Provider'; + if($pname eq '_file_') + { + $p->{args} = { %$config }; + } + else + { + if($pname =~ s/^\+//) { + $prov = $pname; + } + else + { + $prov .= "::$pname"; + } + # We copy the args people want from the config + # to the args + $p->{args} ||= {}; + if ($p->{copy_config}) { + map { $p->{args}->{$_} = $config->{$_} } + grep { exists $config->{$_} } + @{ $p->{copy_config} }; + } + } + eval "require $prov"; + if(!$@) { + push @providers, "$prov"->new($p->{args}); + } + else + { + $c->log->warn("Can't load $prov, ($@)"); + } + } + } + delete $config->{PROVIDERS}; + if(@providers) { + $config->{LOAD_TEMPLATES} = \@providers; + } + } + + $self->{template} = + Template->new($config) || do { + my $error = Template->error(); + $c->log->error($error); + $c->error($error); + return undef; + }; + + + return $self; +} + +sub process { + my ( $self, $c ) = @_; + + my $template = $c->stash->{template} + || $c->action . $self->config->{TEMPLATE_EXTENSION}; + + unless (defined $template) { + $c->log->debug('No template specified for rendering') if $c->debug; + return 0; + } + + my $output = $self->render($c, $template); + + if (UNIVERSAL::isa($output, 'Template::Exception')) { + my $error = qq/Couldn't render template "$output"/; + $c->log->error($error); + $c->error($error); + return 0; + } + + unless ( $c->response->content_type ) { + $c->response->content_type('text/html; charset=utf-8'); + } + + $c->response->body($output); + + return 1; +} + +sub render { + my ($self, $c, $template, $args) = @_; + + $c->log->debug(qq/Rendering template "$template"/) if $c && $c->debug; + + my $output; + my $vars = { + (ref $args eq 'HASH' ? %$args : %{ $c->stash() }), + $self->template_vars($c) + }; + + local $self->{include_path} = + [ @{ $vars->{additional_template_paths} }, @{ $self->{include_path} } ] + if ref $vars->{additional_template_paths}; + + unless ($self->template->process( $template, $vars, \$output ) ) { + return $self->template->error; + } else { + return $output; + } +} + +sub template_vars { + my ( $self, $c ) = @_; + + return () unless $c; + my $cvar = $self->config->{CATALYST_VAR}; + + defined $cvar + ? ( $cvar => $c ) + : ( + c => $c, + base => $c->req->base, + name => $c->config->{name} + ) +} + + +1; + +__END__ + =head1 DESCRIPTION This is the Catalyst view class for the L