Tag 0.31
Tomas Doran [Thu, 29 Oct 2009 19:31:57 +0000 (19:31 +0000)]
30 files changed:
tags/0.31/Changes [new file with mode: 0644]
tags/0.31/MANIFEST.SKIP [new file with mode: 0644]
tags/0.31/Makefile.PL [new file with mode: 0644]
tags/0.31/lib/Catalyst/Helper/View/TT.pm [new file with mode: 0644]
tags/0.31/lib/Catalyst/Helper/View/TTSite.pm [new file with mode: 0644]
tags/0.31/lib/Catalyst/View/TT.pm [new file with mode: 0644]
tags/0.31/t/01use.t [new file with mode: 0644]
tags/0.31/t/02pod.t [new file with mode: 0644]
tags/0.31/t/03podcoverage.t [new file with mode: 0644]
tags/0.31/t/04pkgconfig.t [new file with mode: 0644]
tags/0.31/t/05appconfig.t [new file with mode: 0644]
tags/0.31/t/06includepath.t [new file with mode: 0644]
tags/0.31/t/07render.t [new file with mode: 0644]
tags/0.31/t/08cycle.t [new file with mode: 0644]
tags/0.31/t/09providers.t [new file with mode: 0644]
tags/0.31/t/10providers.encoding.t [new file with mode: 0644]
tags/0.31/t/11norequest.t [new file with mode: 0644]
tags/0.31/t/lib/TestApp.pm [new file with mode: 0755]
tags/0.31/t/lib/TestApp/Controller/Root.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/FauxProvider.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/View/TT/Appconfig.pm [new file with mode: 0755]
tags/0.31/t/lib/TestApp/View/TT/Encoding.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/View/TT/Includepath.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/View/TT/Includepath2.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/View/TT/Includepath3.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/View/TT/Pkgconfig.pm [new file with mode: 0755]
tags/0.31/t/lib/TestApp/View/TT/Providerconfig.pm [new file with mode: 0644]
tags/0.31/t/lib/TestApp/root/specified_template.tt [new file with mode: 0644]
tags/0.31/t/lib/TestApp/root/test.tt [new file with mode: 0644]
tags/0.31/t/lib/TestApp/root/test_include_path/testpath.tt [new file with mode: 0644]

diff --git a/tags/0.31/Changes b/tags/0.31/Changes
new file mode 100644 (file)
index 0000000..36e3256
--- /dev/null
@@ -0,0 +1,137 @@
+Revision history for Perl extension Catalyst::View::TT.
+
+0.31    2009-10-29 19:26:00
+        - Moved the test actions to their own controller file to silence
+          warning about actions in the app class being deprecated.
+
+0.30    2009-09-12 23:47:00
+        - Doc fixes:
+          + Expand ::V:: to ::View:: (RT #45792)
+          + Expand ::C:: to ::Controller:: and use $c->view('TT')
+            where appropriate (bricas)
+          + Add note about use CGI in a template making Catalyst hang
+            (Gunnar Strand)
+        - "use warnings" in Catalyst::View::TT and output from the TT helper
+        - Expand TTSite documentation (RT #33838)
+        - Added a test for direct rendering of a template from a view object,
+          without a request.
+        - Added support for running render with a undef context.
+
+0.29    2009-02-20 14:43:00
+        - Remove extra unwanted .gitignore from manifest
+
+0.28    2009-02-17 20:37:00
+        - Change from NEXT to MRO::Compat (t0m)
+        - fix pod generated by the helper (RT #33983)
+        - remove stray newline from generated lib/config/col template (RT #35340)
+
+0.27    2008-04-30 12:30:00
+        - Add copy_config support to PROVIDERS
+        - Document providers and support unary plus for fully qualified class
+          names as in the example in TT pod.
+
+0.26    2008-01-11 20:12:00
+        - Fix pod coverage
+        - Change from =item to =head2
+        - Update docs to reflect action change
+
+0.25    2007-01-15 16:06
+        - The little typo that cold
+
+0.24    2006-11-15 16:34
+        - Default to .tt extension
+        - pod cleanups for generated file
+        - Move to Module::Install
+        - Use Data::Dump for debug
+
+0.23    Sun Mar 23 20:45:00 2006
+        - Added render suport. (Ash Berlin)
+
+0.22   Fri Jan 16 18:25:00 2006
+        - stringify $c->action for automatic template match instead of $c->req->action.
+             * NOTE * This will change the match to the private name of the matched action!
+          if you use template_suffix you have to move your templates around!
+
+0.21   Fri Dec 16 18:25:00 2005
+        - Added Template::Provider support (Jess Robinson)
+        - Fixed dynamic include bugs and added tests. (Zbigniew Lukasiak)
+
+0.20    Mon Dec 12 03:35:00 2005
+        - Fall back to action (default/index returns blank on match)
+        - Added tests. (Daniel Westermann-Clark)
+        - Fixed TTSite helper to use correct app name.
+        - Added support for dynamic includes.
+
+0.19    Tue Nov 15 09:52:00 2005
+        - unbreak config.
+
+0.18    Mon Nov 14 20:43:00 2005
+        - Fixed more typos
+
+0.17    Mon Nov 14 20:43:00 2005
+        - Fixed some typos
+
+0.16    Mon Nov 14 20:43:00 2005
+        - Updated TTSite for Catalyst 5.5
+
+0.15    Mon Nov 14 14:43:00 2005
+        - Updated for Catalyst 5.5
+        - Fix docs
+        - Added TEMPLATE_SUFFIX config variable 
+
+0.14    Fri Oct 21 10:20:00 2005
+        - Turn timer off by default, even for debug.
+       - removed superflous 'templates' inside 'root'
+       - made it possible to forward to the message action by
+         passing the message in the stash. (example)
+        - Updated docs to show correct config syntax.
+
+0.13    Fri Oct 07 13:30:00 2005
+        - Fixed constructor
+        - Big update by Andy Wardley
+        - Much improved docs
+
+0.12    Wed Jul 06 15:24:00 2005
+        - Fixed, don't set Content-Type on failure
+        - Fixed helper to use [%author%]
+        - Fixed helper templates
+        - Rewrote docs
+
+0.11    Fri Apr 15 16:00:00 2005
+        - Fixed broken helper.
+
+0.10    Fri Apr 15 16:00:00 2005
+        - Added POD tests and made them pass.
+        - updated for Catalyst 5
+        - New TT Helpers.
+
+0.09    Wed Mar 29 13:47:00 2005
+        - Don't override user-set charset/content-type
+        - Cleaned up the content-type we set.
+        - Updated README to current POD to current POD
+
+0.08    Wed Mar 29 12:22:00 2005
+        - changed order of stash so stash can override c/base/name
+        - fixed some typos
+        - extended the documentation (Andrew Ford)
+
+0.07    Sat Mar 04 23:00:00 2005
+        - fixed the bugs produced by draven and the_jester ;)
+
+0.06    Fri Mar 04 20:00:00 2005
+        - new helper api
+
+0.05    Mon Feb 28 10:00:00 2005
+        - added helper
+
+0.04    Sun Feb 27 22:00:00 2005
+        - better debug messages (Marcus Ramberg)
+
+0.03    Thu Feb 17 22:00:00 2005
+        - don't try to render something without a template
+
+0.02    Tue Feb 01 02:00:00 2005
+        - using $c->req->match instead of $c->req->action
+
+0.01    Fri Jan 28 22:00:00 2005
+        - first release
diff --git a/tags/0.31/MANIFEST.SKIP b/tags/0.31/MANIFEST.SKIP
new file mode 100644 (file)
index 0000000..57351d7
--- /dev/null
@@ -0,0 +1,32 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+,v$
+\B\.svn\b
+\B\.git\b
+\B\.gitignore\b
+
+# Avoid Makemaker generated and utility files.
+\bMakefile$
+\bblib
+\bMakeMaker-\d
+\bpm_to_blib$
+\bblibdirs$
+^MANIFEST\.SKIP$
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build
+
+# Avoid temp and backup files.
+~$
+\.tmp$
+\.old$
+\.bak$
+\#$
+\b\.#
+\.DS_Store$
+
+# No tarballs!
+\.gz$
+
diff --git a/tags/0.31/Makefile.PL b/tags/0.31/Makefile.PL
new file mode 100644 (file)
index 0000000..159bb72
--- /dev/null
@@ -0,0 +1,24 @@
+use inc::Module::Install 0.87;
+
+if ( -e 'MANIFEST.SKIP' ) {
+    system( 'pod2text lib/Catalyst/View/TT.pm > README' );
+}
+
+perl_version '5.008001';
+
+name 'Catalyst-View-TT';
+all_from 'lib/Catalyst/View/TT.pm';
+
+requires 'Catalyst'        => '5.7';
+requires 'Template'        => 0;
+requires 'Class::Accessor' => 0;
+requires 'Template::Timer' => 0;
+requires 'Path::Class'     => 0;
+requires 'MRO::Compat'     => 0;
+
+test_requires 'Test::More';
+
+auto_install;
+resources repository => 'http://dev.catalyst.perl.org/repos/Catalyst/trunk/Catalyst-View-TT/';
+
+WriteAll;
diff --git a/tags/0.31/lib/Catalyst/Helper/View/TT.pm b/tags/0.31/lib/Catalyst/Helper/View/TT.pm
new file mode 100644 (file)
index 0000000..6c9462f
--- /dev/null
@@ -0,0 +1,83 @@
+package Catalyst::Helper::View::TT;
+
+use strict;
+
+=head1 NAME
+
+Catalyst::Helper::View::TT - Helper for TT Views
+
+=head1 SYNOPSIS
+
+    script/create.pl view TT TT
+
+=head1 DESCRIPTION
+
+Helper for TT Views.
+
+=head2 METHODS
+
+=head3 mk_compclass
+
+=cut
+
+sub mk_compclass {
+    my ( $self, $helper ) = @_;
+    my $file = $helper->{file};
+    $helper->render_file( 'compclass', $file );
+}
+
+=head1 SEE ALSO
+
+L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
+L<Catalyst::Response>, L<Catalyst::Helper>
+
+=head1 AUTHOR
+
+Sebastian Riedel, C<sri@oook.de>
+Marcus Ramberg, C<mramberg@cpan.org>
+
+=head1 LICENSE
+
+This library is free software . You can redistribute it and/or modify
+it under the same terms as perl itself.
+
+=cut
+
+1;
+
+__DATA__
+
+__compclass__
+package [% class %];
+
+use strict;
+use warnings;
+
+use base 'Catalyst::View::TT';
+
+__PACKAGE__->config(TEMPLATE_EXTENSION => '.tt');
+
+=head1 NAME
+
+[% class %] - TT View for [% app %]
+
+=head1 DESCRIPTION
+
+TT View for [% app %].
+
+=head1 SEE ALSO
+
+L<[% app %]>
+
+=head1 AUTHOR
+
+[% author %]
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
diff --git a/tags/0.31/lib/Catalyst/Helper/View/TTSite.pm b/tags/0.31/lib/Catalyst/Helper/View/TTSite.pm
new file mode 100644 (file)
index 0000000..90f9825
--- /dev/null
@@ -0,0 +1,391 @@
+package Catalyst::Helper::View::TTSite;
+
+use strict;
+use File::Spec;
+
+sub mk_compclass {
+    my ( $self, $helper, @args ) = @_;
+    my $file = $helper->{file};
+    $helper->render_file( 'compclass', $file );
+    $self->mk_templates( $helper, @args );
+}
+
+sub mk_templates {
+    my ( $self, $helper ) = @_;
+    my $base = $helper->{base},;
+    my $ldir = File::Spec->catfile( $base, 'root', 'lib' );
+    my $sdir = File::Spec->catfile( $base, 'root', 'src' );
+
+    $helper->mk_dir($ldir);
+    $helper->mk_dir($sdir);
+
+    my $dir = File::Spec->catfile( $ldir, 'config' );
+    $helper->mk_dir($dir);
+
+    foreach my $file (qw( main col url )) {
+        $helper->render_file( "config_$file",
+            File::Spec->catfile( $dir, $file ) );
+    }
+
+    $dir = File::Spec->catfile( $ldir, 'site' );
+    $helper->mk_dir($dir);
+
+    foreach my $file (qw( wrapper layout html header footer )) {
+        $helper->render_file( "site_$file",
+            File::Spec->catfile( $dir, $file ) );
+    }
+
+    foreach my $file (qw( welcome.tt2 message.tt2 error.tt2 ttsite.css )) {
+        $helper->render_file( $file, File::Spec->catfile( $sdir, $file ) );
+    }
+
+}
+
+=head1 NAME
+
+Catalyst::Helper::View::TTSite - Helper for TT view which builds a skeleton web site
+
+=head1 SYNOPSIS
+
+# use the helper to create the view module and templates
+
+    $ script/myapp_create.pl view TT TTSite
+
+# add something like the following to your main application module
+
+    sub message : Global {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'message.tt2';
+        $c->stash->{message}  ||= $c->req->param('message') || 'No message';
+    }
+
+    sub default : Private {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'welcome.tt2';
+    }
+
+    sub end : Private {
+        my ( $self, $c ) = @_;
+        $c->forward( $c->view('TT') );
+    }
+
+=head1 DESCRIPTION
+
+This helper module creates a TT View module.  It goes further than
+Catalyst::Helper::View::TT in that it additionally creates a simple
+set of templates to get you started with your web site presentation.
+
+It creates the templates in F<root/> directory underneath your
+main project directory.  In here two further subdirectories are
+created: F<root/src> which contains the main page templates, and F<root/lib>
+containing a library of other template components (header, footer,
+etc.) that the page templates use.
+
+The view module that the helper creates is automatically configured
+to locate these templates.
+
+=head2 Default Rendering
+
+To render a template the following process is applied:
+
+The configuration template F<root/lib/config/main> is rendered. This is
+controlled by the C<PRE_PROCESS> configuration variable set in the controller
+generated by Catalyst::Helper::View::TTsite. Additionally, templates referenced by
+the C<PROCESS> directive will then be rendered. By default the following additional
+templates are set: F<root/lib/config/col>,
+which defines color names and RGB their RGB values and F</root/lib/config/url>,
+which defines site wide variables available to templates.
+
+Next, the template defined by the C<WRAPPER> config variable is called. The default
+wrapper template is located in F<root/lib/site/wrapper>. The wrapper template
+passes files with C<.css/.js/.txt> extensions through as text OR processes
+the templates defined after the C<WRAPPER> directive: C<site/html> and C<site/layout>.
+
+Based on the default value of the C<WRAPPER> directive in F<root/lib/site/wrapper>,
+the following templates are processed in order:
+
+=over 4
+
+=item * F<root/src/your_template.tt2>
+
+=item * F<root/lib/site/footer>
+
+=item * F<root/lib/site/header>
+
+=item * F<root/lib/site/layout>
+
+=item * F<root/lib/site/html>
+
+=back
+
+Finally, the rendered content is returned to the bowser.
+
+=head1 METHODS
+
+=head2 mk_compclass
+
+Generates the component class.
+
+=head2 mk_templates
+
+Generates the templates.
+
+=cut
+
+=head1 SEE ALSO
+
+L<Catalyst>, L<Catalyst::View::TT>, L<Catalyst::Helper>,
+L<Catalyst::Helper::View::TT>
+
+=head1 AUTHOR
+
+Andy Wardley <abw@cpan.org>
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as perl itself.
+
+=cut
+
+1;
+
+__DATA__
+
+__compclass__
+package [% class %];
+
+use strict;
+use base 'Catalyst::View::TT';
+
+__PACKAGE__->config({
+    INCLUDE_PATH => [
+        [% app %]->path_to( 'root', 'src' ),
+        [% app %]->path_to( 'root', 'lib' )
+    ],
+    PRE_PROCESS  => 'config/main',
+    WRAPPER      => 'site/wrapper',
+    ERROR        => 'error.tt2',
+    TIMER        => 0
+});
+
+=head1 NAME
+
+[% class %] - Catalyst TTSite View
+
+=head1 SYNOPSIS
+
+See L<[% app %]>
+
+=head1 DESCRIPTION
+
+Catalyst TTSite View.
+
+=head1 AUTHOR
+
+[% author %]
+
+=head1 LICENSE
+
+This library is free software. You can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+=cut
+
+1;
+
+__config_main__
+[% USE Date;
+   year = Date.format(Date.now, '%Y');
+-%]
+[% TAGS star -%]
+[% # config/main
+   #
+   # This is the main configuration template which is processed before
+   # any other page, by virtue of it being defined as a PRE_PROCESS
+   # template.  This is the place to define any extra template variables,
+   # macros, load plugins, and perform any other template setup.
+
+   IF Catalyst.debug;
+     # define a debug() macro directed to Catalyst's log
+     MACRO debug(message) CALL Catalyst.log.debug(message);
+   END;
+
+   # define a data structure to hold sitewide data
+   site = {
+     title     => 'Catalyst::View::TTSite Example Page',
+     copyright => '[* year *] Your Name Here',
+   };
+
+   # load up any other configuration items
+   PROCESS config/col
+         + config/url;
+
+   # set defaults for variables, etc.
+   DEFAULT
+     message = 'There is no message';
+
+-%]
+__config_col__
+[% TAGS star -%]
+[% site.rgb = {
+     black  = '#000000'
+     white  = '#ffffff'
+     grey1  = '#46494c'
+     grey2  = '#c6c9cc'
+     grey3  = '#e3e6ea'
+     red    = '#CC4444'
+     green  = '#66AA66'
+     blue   = '#89b8df'
+     orange = '#f08900'
+   };
+
+   site.col = {
+      page    = site.rgb.white
+      text    = site.rgb.grey1
+      head    = site.rgb.grey3
+      line    = site.rgb.orange
+      message = site.rgb.green
+      error   = site.rgb.red
+   };
+-%]
+__config_url__
+[% TAGS star -%]
+[% base = Catalyst.req.base;
+
+   site.url = {
+     base    = base
+     home    = "${base}welcome"
+     message = "${base}message"
+   }
+-%]
+__site_wrapper__
+[% TAGS star -%]
+[% IF template.name.match('\.(css|js|txt)');
+     debug("Passing page through as text: $template.name");
+     content;
+   ELSE;
+     debug("Applying HTML page layout wrappers to $template.name\n");
+     content WRAPPER site/html + site/layout;
+   END;
+-%]
+__site_html__
+[% TAGS star -%]
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+  <title>[% template.title or site.title %]</title>
+  <style type="text/css">
+[% PROCESS ttsite.css %]
+  </style>
+ </head>
+ <body>
+[% content %]
+ </body>
+</html>
+__site_layout__
+[% TAGS star -%]
+<div id="header">[% PROCESS site/header %]</div>
+
+<div id="content">
+[% content %]
+</div>
+
+<div id="footer">[% PROCESS site/footer %]</div>
+__site_header__
+[% TAGS star -%]
+<!-- BEGIN site/header -->
+<h1 class="title">[% template.title or site.title %]</h1>
+<!-- END site/header -->
+__site_footer__
+[% TAGS star -%]
+<!-- BEGIN site/footer -->
+<div id="copyright">&copy; [% site.copyright %]</div>
+<!-- END site/footer -->
+__welcome.tt2__
+[% TAGS star -%]
+[% META title = 'Catalyst/TT View!' %]
+<p>
+  Yay!  You're looking at a page generated by the Catalyst::View::TT
+  plugin module.
+</p>
+<p>
+  This is the welcome page.  Why not try the equally-exciting
+  <a href="[% site.url.message %]">Message Page</a>?
+</p>
+__message.tt2__
+[% TAGS star -%]
+[% META title = 'Catalyst/TT View!' %]
+<p>
+  Yay!  You're looking at a page generated by the Catalyst::View::TT
+  plugin module.
+</p>
+<p>
+  We have a message for you: <span class="message">[% message %]</span>.
+</p>
+<p>
+  Why not try updating the message?  Go on, it's really exciting, honest!
+</p>
+<form action="[% site.url.message %]"
+      method="POST" enctype="application/x-www-form-urlencoded">
+ <input type="text" name="message" value="[% message %]" />
+ <input type="submit" name="submit" value=" Update Message "/>
+</form>
+__error.tt2__
+[% TAGS star -%]
+[% META title = 'Catalyst/TT Error' %]
+<p>
+  An error has occurred.  We're terribly sorry about that, but it's
+  one of those things that happens from time to time.  Let's just
+  hope the developers test everything properly before release...
+</p>
+<p>
+  Here's the error message, on the off-chance that it means something
+  to you: <span class="error">[% error %]</span>
+</p>
+__ttsite.css__
+[% TAGS star %]
+html {
+    height: 100%;
+}
+
+body {
+    background-color: [% site.col.page %];
+    color: [% site.col.text %];
+    margin: 0px;
+    padding: 0px;
+    height: 100%;
+}
+
+#header {
+    background-color: [% site.col.head %];
+    border-bottom: 1px solid [% site.col.line %];
+}
+
+#footer {
+    background-color: [% site.col.head %];
+    text-align: center;
+    border-top: 1px solid [% site.col.line %];
+    position: absolute;
+    bottom: 0;
+    left: 0px;
+    width: 100%;
+    padding: 4px;
+}
+
+#content {
+    padding: 10px;
+}
+
+h1.title {
+    padding: 4px;
+    margin: 0px;
+}
+
+.message {
+    color: [% site.col.message %];
+}
+
+.error {
+    color: [% site.col.error %];
+}
diff --git a/tags/0.31/lib/Catalyst/View/TT.pm b/tags/0.31/lib/Catalyst/View/TT.pm
new file mode 100644 (file)
index 0000000..d07faba
--- /dev/null
@@ -0,0 +1,675 @@
+package Catalyst::View::TT;
+
+use strict;
+use warnings;
+
+use base qw/Catalyst::View/;
+use Data::Dump 'dump';
+use Template;
+use Template::Timer;
+use MRO::Compat;
+
+our $VERSION = '0.31';
+
+__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 your View
+
+    myapp_create.pl view TT TT
+
+# configure in lib/MyApp.pm (Could be set from configfile instead)
+
+    MyApp->config(
+        name     => 'MyApp',
+        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' ),
+            ],
+            TEMPLATE_EXTENSION => '.tt',
+            CATALYST_VAR => 'c',
+            TIMER        => 0,
+            # Not set by default
+            PRE_PROCESS        => 'config/main',
+            WRAPPER            => 'site/wrapper',
+        },
+    );
+
+# 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( $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 %]
+
+    # 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<Template Toolkit|Template>.
+Your application should defined a view class which is a subclass of
+this module.  The easiest way to achieve this is using the
+F<myapp_create.pl> script (where F<myapp> should be replaced with
+whatever your application is called).  This script is created as part
+of the Catalyst setup.
+
+    $ script/myapp_create.pl view TT TT
+
+This creates a MyApp::View::TT.pm module in the F<lib> directory (again,
+replacing C<MyApp> with the name of your application) which looks
+something like this:
+
+    package FooBar::View::TT;
+
+    use strict;
+    use warnings;
+
+    use base 'Catalyst::View::TT';
+
+    __PACKAGE__->config->{DEBUG} = 'all';
+
+Now you can modify your action handlers in the main application and/or
+controllers to forward to your view class.  You might choose to do this
+in the end() method, for example, to automatically forward all actions
+to the TT view class.
+
+    # In MyApp or MyApp::Controller::SomeController
+
+    sub end : Private {
+        my( $self, $c ) = @_;
+        $c->forward( $c->view('TT') );
+    }
+
+=head2 CONFIGURATION
+
+There are a three different ways to configure your view class.  The
+first way is to call the C<config()> method in the view subclass.  This
+happens when the module is first loaded.
+
+    package MyApp::View::TT;
+
+    use strict;
+    use base 'Catalyst::View::TT';
+
+    MyApp::View::TT->config({
+        INCLUDE_PATH => [
+            MyApp->path_to( 'root', 'templates', 'lib' ),
+            MyApp->path_to( 'root', 'templates', 'src' ),
+        ],
+        PRE_PROCESS  => 'config/main',
+        WRAPPER      => 'site/wrapper',
+    });
+
+The second way is to define a C<new()> method in your view subclass.
+This performs the configuration when the view object is created,
+shortly after being loaded.  Remember to delegate to the base class
+C<new()> method (via C<$self-E<gt>next::method()> in the example below) after
+performing any configuration.
+
+    sub new {
+        my $self = shift;
+        $self->config({
+            INCLUDE_PATH => [
+                MyApp->path_to( 'root', 'templates', 'lib' ),
+                MyApp->path_to( 'root', 'templates', 'src' ),
+            ],
+            PRE_PROCESS  => 'config/main',
+            WRAPPER      => 'site/wrapper',
+        });
+        return $self->next::method(@_);
+    }
+
+The final, and perhaps most direct way, is to define a class
+item in your main application configuration, again by calling the
+ubiquitous C<config()> method.  The items in the class hash are
+added to those already defined by the above two methods.  This happens
+in the base class new() method (which is one reason why you must
+remember to call it via C<MRO::Compat> if you redefine the C<new()>
+method in a subclass).
+
+    package MyApp;
+
+    use strict;
+    use Catalyst;
+
+    MyApp->config({
+        name     => 'MyApp',
+        root     => MyApp->path_to('root'),
+        'View::TT' => {
+            INCLUDE_PATH => [
+                MyApp->path_to( 'root', 'templates', 'lib' ),
+                MyApp->path_to( 'root', 'templates', 'src' ),
+            ],
+            PRE_PROCESS  => 'config/main',
+            WRAPPER      => 'site/wrapper',
+        },
+    });
+
+Note that any configuration items defined by one of the earlier
+methods will be overwritten by items of the same name provided by the
+latter methods.
+
+=head2 DYNAMIC INCLUDE_PATH
+
+Sometimes it is desirable to modify INCLUDE_PATH for your templates at run time.
+
+Additional paths can be added to the start of INCLUDE_PATH via the stash as
+follows:
+
+    $c->stash->{additional_template_paths} =
+        [$c->config->{root} . '/test_include_path'];
+
+If you need to add paths to the end of INCLUDE_PATH, there is also an
+include_path() accessor available:
+
+    push( @{ $c->view('TT')->include_path }, qw/path/ );
+
+Note that if you use include_path() to add extra paths to INCLUDE_PATH, you
+MUST check for duplicate paths. Without such checking, the above code will add
+"path" to INCLUDE_PATH at every request, causing a memory leak.
+
+A safer approach is to use include_path() to overwrite the array of paths
+rather than adding to it. This eliminates both the need to perform duplicate
+checking and the chance of a memory leak:
+
+    @{ $c->view('TT')->include_path } = qw/path another_path/;
+
+If you are calling C<render> directly then you can specify dynamic paths by
+having a C<additional_template_paths> key with a value of additonal directories
+to search. See L<CAPTURING TEMPLATE OUTPUT> for an example showing this.
+
+=head2 RENDERING VIEWS
+
+The view plugin renders the template specified in the C<template>
+item in the stash.
+
+    sub message : Global {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'message.tt2';
+        $c->forward( $c->view('TT') );
+    }
+
+If a stash item isn't defined, then it instead uses the
+stringification of the action dispatched to (as defined by $c->action)
+in the above example, this would be C<message>, but because the default
+is to append '.tt', it would load C<root/message.tt>.
+
+The items defined in the stash are passed to the Template Toolkit for
+use as template variables.
+
+    sub default : Private {
+        my ( $self, $c ) = @_;
+        $c->stash->{template} = 'message.tt2';
+        $c->stash->{message}  = 'Hello World!';
+        $c->forward( $c->view('TT') );
+    }
+
+A number of other template variables are also added:
+
+    c      A reference to the context object, $c
+    base   The URL base, from $c->req->base()
+    name   The application name, from $c->config->{ name }
+
+These can be accessed from the template in the usual way:
+
+<message.tt2>:
+
+    The message is: [% message %]
+    The base is [% base %]
+    The name is [% name %]
+
+
+The output generated by the template is stored in C<< $c->response->body >>.
+
+=head2 CAPTURING TEMPLATE OUTPUT
+
+If you wish to use the output of a template for some other purpose than
+displaying in the response, e.g. for sending an email, this is possible using
+L<Catalyst::Plugin::Email> and the L<render> method:
+
+  sub send_email : Local {
+    my ($self, $c) = @_;
+
+    $c->email(
+      header => [
+        To      => 'me@localhost',
+        Subject => 'A TT Email',
+      ],
+      body => $c->view('TT')->render($c, 'email.tt', {
+        additional_template_paths => [ $c->config->{root} . '/email_templates'],
+        email_tmpl_param1 => 'foo'
+        }
+      ),
+    );
+  # Redirect or display a message
+  }
+
+=head2 TEMPLATE PROFILING
+
+See L<C<TIMER>> property of the L<config> method.
+
+=head2 METHODS
+
+=head2 new
+
+The constructor for the TT view. Sets up the template provider,
+and reads the application config.
+
+=head2 process($c)
+
+Renders the template specified in C<< $c->stash->{template} >> or
+C<< $c->action >> (the private name of the matched action).  Calls L<render> to
+perform actual rendering. Output is stored in C<< $c->response->body >>.
+
+It is possible to forward to the process method of a TT view from inside
+Catalyst like this:
+
+    $c->forward('View::TT');
+
+N.B. This is usually done automatically by L<Catalyst::Action::RenderView>.
+
+=head2 render($c, $template, \%args)
+
+Renders the given template and returns output, or a L<Template::Exception>
+object upon error.
+
+The template variables are set to C<%$args> if $args is a hashref, or
+$C<< $c->stash >> otherwise. In either case the variables are augmented with
+C<base> set to C< << $c->req->base >>, C<c> to C<$c> and C<name> to
+C<< $c->config->{name} >>. Alternately, the C<CATALYST_VAR> configuration item
+can be defined to specify the name of a template variable through which the
+context reference (C<$c>) can be accessed. In this case, the C<c>, C<base> and
+C<name> variables are omitted.
+
+C<$template> can be anything that Template::process understands how to
+process, including the name of a template file or a reference to a test string.
+See L<Template::process|Template/process> for a full list of supported formats.
+
+To use the render method outside of your Catalyst app, just pass a undef context.
+This can be useful for tests, for instance.
+
+It is possible to forward to the render method of a TT view from inside Catalyst
+to render page fragments like this:
+
+    my $fragment = $c->forward("View::TT", "render", $template_name, $c->stash->{fragment_data});
+
+=head2 template_vars
+
+Returns a list of keys/values to be used as the catalyst variables in the
+template.
+
+=head2 config
+
+This method allows your view subclass to pass additional settings to
+the TT configuration hash, or to set the options as below:
+
+=head2 paths
+
+The list of paths TT will look for templates in.
+
+=head2 C<CATALYST_VAR>
+
+Allows you to change the name of the Catalyst context object. If set, it will also
+remove the base and name aliases, so you will have access them through <context>.
+
+For example:
+
+    MyApp->config({
+        name     => 'MyApp',
+        root     => MyApp->path_to('root'),
+        'View::TT' => {
+            CATALYST_VAR => 'Catalyst',
+        },
+    });
+
+F<message.tt2>:
+
+    The base is [% Catalyst.req.base %]
+    The name is [% Catalyst.config.name %]
+
+=head2 C<TIMER>
+
+If you have configured Catalyst for debug output, and turned on the TIMER setting,
+C<Catalyst::View::TT> will enable profiling of template processing
+(using L<Template::Timer>). This will embed HTML comments in the
+output from your templates, such as:
+
+    <!-- TIMER START: process mainmenu/mainmenu.ttml -->
+    <!-- TIMER START: include mainmenu/cssindex.tt -->
+    <!-- TIMER START: process mainmenu/cssindex.tt -->
+    <!-- TIMER END: process mainmenu/cssindex.tt (0.017279 seconds) -->
+    <!-- TIMER END: include mainmenu/cssindex.tt (0.017401 seconds) -->
+
+    ....
+
+    <!-- TIMER END: process mainmenu/footer.tt (0.003016 seconds) -->
+
+
+=head2 C<TEMPLATE_EXTENSION>
+
+a sufix to add when looking for templates bases on the C<match> method in L<Catalyst::Request>.
+
+For example:
+
+  package MyApp::Controller::Test;
+  sub test : Local { .. }
+
+Would by default look for a template in <root>/test/test. If you set TEMPLATE_EXTENSION to '.tt', it will look for
+<root>/test/test.tt.
+
+=head2 C<PROVIDERS>
+
+Allows you to specify the template providers that TT will use.
+
+    MyApp->config({
+        name     => 'MyApp',
+        root     => MyApp->path_to('root'),
+        'View::TT' => {
+            PROVIDERS => [
+                {
+                    name    => 'DBI',
+                    args    => {
+                        DBI_DSN => 'dbi:DB2:books',
+                        DBI_USER=> 'foo'
+                    }
+                }, {
+                    name    => '_file_',
+                    args    => {}
+                }
+            ]
+        },
+    });
+
+The 'name' key should correspond to the class name of the provider you
+want to use.  The _file_ name is a special case that represents the default
+TT file-based provider.  By default the name is will be prefixed with
+'Template::Provider::'.  You can fully qualify the name by using a unary
+plus:
+
+    name => '+MyApp::Provider::Foo'
+
+You can also specify the 'copy_config' key as an arrayref, to copy those keys
+from the general config, into the config for the provider:
+
+    DEFAULT_ENCODING    => 'utf-8',
+    PROVIDERS => [
+        {
+            name    => 'Encoding',
+            copy_config => [qw(DEFAULT_ENCODING INCLUDE_PATH)]
+        }
+    ]
+
+This can prove useful when you want to use the additional_template_paths hack
+in your own provider, or if you need to use Template::Provider::Encoding
+
+=head2 HELPERS
+
+The L<Catalyst::Helper::View::TT> and
+L<Catalyst::Helper::View::TTSite> helper modules are provided to create
+your view module.  There are invoked by the F<myapp_create.pl> script:
+
+    $ script/myapp_create.pl view TT TT
+
+    $ script/myapp_create.pl view TT TTSite
+
+The L<Catalyst::Helper::View::TT> module creates a basic TT view
+module.  The L<Catalyst::Helper::View::TTSite> module goes a little
+further.  It also creates a default set of templates to get you
+started.  It also configures the view module to locate the templates
+automatically.
+
+=head1 NOTES
+
+If you are using the L<CGI> module inside your templates, you will
+experience that the Catalyst server appears to hang while rendering
+the web page. This is due to the debug mode of L<CGI> (which is
+waiting for input in the terminal window). Turning off the
+debug mode using the "-no_debug" option solves the
+problem, eg.:
+
+    [% USE CGI('-no_debug') %]
+
+=head1 SEE ALSO
+
+L<Catalyst>, L<Catalyst::Helper::View::TT>,
+L<Catalyst::Helper::View::TTSite>, L<Template::Manual>
+
+=head1 AUTHORS
+
+Sebastian Riedel, C<sri@cpan.org>
+
+Marcus Ramberg, C<mramberg@cpan.org>
+
+Jesse Sheidlower, C<jester@panix.com>
+
+Andy Wardley, C<abw@cpan.org>
+
+=head1 COPYRIGHT
+
+This program is free software. You can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
diff --git a/tags/0.31/t/01use.t b/tags/0.31/t/01use.t
new file mode 100644 (file)
index 0000000..ccc1771
--- /dev/null
@@ -0,0 +1,5 @@
+use strict;
+use Test::More tests => 2;
+
+BEGIN { use_ok('Catalyst::View::TT') }
+BEGIN { use_ok('Catalyst::Helper::View::TT') }
diff --git a/tags/0.31/t/02pod.t b/tags/0.31/t/02pod.t
new file mode 100644 (file)
index 0000000..1647794
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+
+eval "use Test::Pod 1.14";
+plan skip_all => 'Test::Pod 1.14 required' if $@;
+plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
+
+all_pod_files_ok();
diff --git a/tags/0.31/t/03podcoverage.t b/tags/0.31/t/03podcoverage.t
new file mode 100644 (file)
index 0000000..d91be5e
--- /dev/null
@@ -0,0 +1,7 @@
+use Test::More;
+
+eval "use Test::Pod::Coverage 1.04";
+plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@;
+plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD};
+
+all_pod_coverage_ok();
diff --git a/tags/0.31/t/04pkgconfig.t b/tags/0.31/t/04pkgconfig.t
new file mode 100644 (file)
index 0000000..9d64e02
--- /dev/null
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $view = 'Pkgconfig';
+
+my $response;
+ok(($response = request("/test?view=$view"))->is_success, 'request ok');
+is($response->content, TestApp->config->{default_message}, 'message ok');
+
+my $message = scalar localtime;
+ok(($response = request("/test?view=$view&message=$message"))->is_success, 'request with message ok');
+is($response->content,  $message, 'message ok')
diff --git a/tags/0.31/t/05appconfig.t b/tags/0.31/t/05appconfig.t
new file mode 100644 (file)
index 0000000..ff6e5fd
--- /dev/null
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $view = 'Appconfig';
+
+my $response;
+ok(($response = request("/test?view=$view"))->is_success, 'request ok');
+is($response->content, TestApp->config->{default_message}, 'message ok');
+
+my $message = scalar localtime;
+ok(($response = request("/test?view=$view&message=$message"))->is_success, 'request with message ok');
+is($response->content, $message, 'message ok')
diff --git a/tags/0.31/t/06includepath.t b/tags/0.31/t/06includepath.t
new file mode 100644 (file)
index 0000000..70001f5
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use Test::More tests => 10;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+my $response;
+
+my $inital_include_path = [ @{ TestApp->view('TT::Appconfig')->include_path } ];
+
+ok(($response = request("/test_includepath?view=Appconfig&template=testpath.tt&additionalpath=test_include_path"))->is_success, 'additional_template_path request');
+is($response->content, TestApp->config->{default_message}, 'additional_template_path message');
+
+is_deeply($inital_include_path,
+    TestApp->view('TT::Appconfig')->include_path,
+    'Include path is unchanged');
+
+ok(($response = request("/test_includepath?view=Includepath&template=testpath.tt"))->is_success, 'scalar include path from config request');
+is($response->content, TestApp->config->{default_message}, 'scalar include path with delimiter from config message');
+
+ok(($response = request("/test_includepath?view=Includepath2&template=testpath.tt"))->is_success, 'object ref (that stringifys to the path) include path from config request');
+is($response->content, TestApp->config->{default_message}, 'object ref (that stringifys to the path) include path from config message');
+
+ok(($response = request("/test_includepath?view=Includepath3&template=testpath.tt&addpath=test_include_path"))->is_success, 'array ref include path from config not replaced by another array request');
+is($response->content, TestApp->config->{default_message}, 'array ref include path from config not replaced by another array message');
+
diff --git a/tags/0.31/t/07render.t b/tags/0.31/t/07render.t
new file mode 100644 (file)
index 0000000..71e98b5
--- /dev/null
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+use Test::More tests => 7;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $response;
+ok(($response = request("/test_render?template=specified_template.tt&param=parameterized"))->is_success, 'request ok');
+is($response->content, "I should be a parameterized test in @{[TestApp->config->{name}]}", 'message ok');
+
+my $message = 'Dynamic message';
+
+ok(($response = request("/test_msg?msg=$message"))->is_success, 'request ok');
+is($response->content, "$message", 'message ok');
+
+$response = request("/test_render?template=non_existant_template.tt");
+
+is (403, $response->code, 'request returned error');
+is($response->content, 'file error - non_existant_template.tt: not found', 'Error from non-existant-template');
diff --git a/tags/0.31/t/08cycle.t b/tags/0.31/t/08cycle.t
new file mode 100644 (file)
index 0000000..ea41a72
--- /dev/null
@@ -0,0 +1,28 @@
+use strict;
+use warnings;
+use Test::More;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+plan tests => 3;
+
+use_ok('Catalyst::View::TT');
+use_ok('Catalyst::Test', 'TestApp');
+
+my $copy;
+{
+    my $view = new Catalyst::View::TT("TestApp", {});
+
+    # Can't Test::Memory::Cycle test since it doesn't detect 
+    #  [ sub { $copy->paths } ]
+    # as a cycle, but the above does prevent it getting garbage collected.
+    #
+    # memory_cycle_ok($view, 'No cycles in View');
+
+    $copy = $view;
+    Scalar::Util::weaken($copy);
+}
+
+ok(!defined $copy, 'Copy went out of scope');
+
diff --git a/tags/0.31/t/09providers.t b/tags/0.31/t/09providers.t
new file mode 100644 (file)
index 0000000..0a70320
--- /dev/null
@@ -0,0 +1,16 @@
+use strict;
+use warnings;
+use Test::More tests => 5;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $response;
+ok(($response = request("/test_includepath?view=Providerconfig&template=test.tt"))->is_success, 'provider request');
+cmp_ok($response->content, 'eq', 'Faux-tastic!', 'provider worked');
+
+
+ok(($response = request("/test_includepath?view=Providerconfig&template=testpath.tt&additionalpath=test_include_path"))->is_success, 'provider request');
+cmp_ok($response->content, 'eq', 'Faux-tastic!', 'provider worked');
diff --git a/tags/0.31/t/10providers.encoding.t b/tags/0.31/t/10providers.encoding.t
new file mode 100644 (file)
index 0000000..7027ecb
--- /dev/null
@@ -0,0 +1,20 @@
+use strict;
+use warnings;
+use Test::More;
+
+eval "use Template::Provider::Encoding";
+if ($@) {
+    plan skip_all => 'Template::Provider::Encoding';
+} else {
+    plan tests => 3;
+}
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+use_ok('Catalyst::Test', 'TestApp');
+
+my $response;
+ok(($response = request("/test_includepath?view=Encoding&template=test.tt&additionalpath=test_include_path"))->is_success, 'provider request');
+cmp_ok($response->content, 'eq', 'hi', 'provider worked');
+
diff --git a/tags/0.31/t/11norequest.t b/tags/0.31/t/11norequest.t
new file mode 100644 (file)
index 0000000..0aff98a
--- /dev/null
@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+use FindBin;
+use lib "$FindBin::Bin/lib";
+
+BEGIN { use_ok 'TestApp' or die }
+
+ok my $tt = TestApp->view('TT'), 'Get TT view object';
+is $tt->render(undef, 'test.tt', { message => 'hello' }), 'hello',
+    'render() should return the template output';
diff --git a/tags/0.31/t/lib/TestApp.pm b/tags/0.31/t/lib/TestApp.pm
new file mode 100755 (executable)
index 0000000..97bf8f0
--- /dev/null
@@ -0,0 +1,23 @@
+package TestApp;
+
+use strict;
+use warnings;
+
+use Catalyst; # qw/-Debug/;
+use Path::Class;
+
+our $VERSION = '0.01';
+
+__PACKAGE__->config(
+    name                  => 'TestApp',
+    default_message       => 'hi',
+    default_view          => 'Pkgconfig',
+    'View::TT::Appconfig' => {
+        PRE_CHOMP          => 1,
+        POST_CHOMP         => 1,
+        TEMPLATE_EXTENSION => '.tt',
+    },
+);
+
+__PACKAGE__->setup;
+
diff --git a/tags/0.31/t/lib/TestApp/Controller/Root.pm b/tags/0.31/t/lib/TestApp/Controller/Root.pm
new file mode 100644 (file)
index 0000000..e119a1b
--- /dev/null
@@ -0,0 +1,65 @@
+package TestApp::Controller::Root;
+use base 'Catalyst::Controller';
+__PACKAGE__->config(namespace => '');
+
+sub default : Private {
+    my ($self, $c) = @_;
+
+    $c->response->redirect($c->uri_for('test'));
+}
+
+sub test : Local {
+    my ($self, $c) = @_;
+
+    $c->stash->{message} = ($c->request->param('message') || $c->config->{default_message});
+}
+
+sub test_includepath : Local {
+    my ($self, $c) = @_;
+    $c->stash->{message} = ($c->request->param('message') || $c->config->{default_message});
+    $c->stash->{template} = $c->request->param('template');
+    if ( $c->request->param('additionalpath') ){
+        my $additionalpath = Path::Class::dir($c->config->{root}, $c->request->param('additionalpath'));
+        $c->stash->{additional_template_paths} = ["$additionalpath"];
+    }
+    if ( $c->request->param('addpath') ){
+        my $additionalpath = Path::Class::dir($c->config->{root}, $c->request->param('addpath'));
+        my $view = 'TestApp::View::TT::' . ($c->request->param('view') || $c->config->{default_view});
+        no strict "refs";
+        push @{$view . '::include_path'}, "$additionalpath";
+        use strict;
+    }
+}
+
+sub test_render : Local {
+    my ($self, $c) = @_;
+
+    my $out = $c->stash->{message} = $c->view('TT::Appconfig')->render($c, $c->req->param('template'), {param => $c->req->param('param') || ''});
+    if (UNIVERSAL::isa($out, 'Template::Exception')) {
+        $c->response->body($out);
+        $c->response->status(403);
+    } else {
+        $c->stash->{template} = 'test.tt';
+    }
+
+}
+
+sub test_msg : Local {
+    my ($self, $c) = @_;
+    my $tmpl = $c->req->param('msg');
+    
+    $c->stash->{message} = $c->view('TT::AppConfig')->render($c, \$tmpl);
+    $c->stash->{template} = 'test.tt';
+}
+
+sub end : Private {
+    my ($self, $c) = @_;
+
+    return 1 if $c->response->status =~ /^3\d\d$/;
+    return 1 if $c->response->body;
+
+    my $view = 'View::TT::' . ($c->request->param('view') || $c->config->{default_view});
+    $c->forward($view);
+}
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/FauxProvider.pm b/tags/0.31/t/lib/TestApp/FauxProvider.pm
new file mode 100644 (file)
index 0000000..07f9bc3
--- /dev/null
@@ -0,0 +1,23 @@
+package TestApp::FauxProvider;
+
+use Template::Constants;
+
+use base qw(Template::Provider);
+
+sub fetch {
+    my $self = shift();
+    my $name = shift();
+    
+    my $data = {
+        name    => $name,
+        path    => $name,
+        text    => 'Faux-tastic!',
+        'time'  => time(),
+        load    => time()
+    };
+
+    my ($page, $error) = $self->_compile($data);
+    return ($page->{'data'}, $error);
+}
+
+1;
\ No newline at end of file
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Appconfig.pm b/tags/0.31/t/lib/TestApp/View/TT/Appconfig.pm
new file mode 100755 (executable)
index 0000000..562ed03
--- /dev/null
@@ -0,0 +1,6 @@
+package TestApp::View::TT::Appconfig;
+
+use strict;
+use base 'Catalyst::View::TT';
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Encoding.pm b/tags/0.31/t/lib/TestApp/View/TT/Encoding.pm
new file mode 100644 (file)
index 0000000..ffa3589
--- /dev/null
@@ -0,0 +1,20 @@
+package TestApp::View::TT::Encoding;
+
+use strict;
+use base 'Catalyst::View::TT';
+
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+    'TEMPLATE_EXTENSION' => '.tt',
+    'DEFAULT_ENCODING'   => 'utf-8',
+    PROVIDERS            => [
+        {
+            name        => 'Encoding',
+            copy_config => [qw(INCLUDE_PATH DEFAULT_ENCODING PRE_CHOMP POST_CHOMP)]
+        }
+    ],
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Includepath.pm b/tags/0.31/t/lib/TestApp/View/TT/Includepath.pm
new file mode 100644 (file)
index 0000000..0d8756d
--- /dev/null
@@ -0,0 +1,16 @@
+package TestApp::View::TT::Includepath;
+
+use FindBin;
+use Path::Class;
+use strict;
+use base 'Catalyst::View::TT';
+
+my $includepath = dir($FindBin::Bin, '/lib/TestApp/root/test_include_path');
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+    INCLUDE_PATH        => "aaa:$includepath",
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Includepath2.pm b/tags/0.31/t/lib/TestApp/View/TT/Includepath2.pm
new file mode 100644 (file)
index 0000000..11f2667
--- /dev/null
@@ -0,0 +1,16 @@
+package TestApp::View::TT::Includepath2;
+
+use FindBin;
+use Path::Class;
+use strict;
+use base 'Catalyst::View::TT';
+
+my $includepath = dir($FindBin::Bin, '/lib/TestApp/root/test_include_path');
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+    INCLUDE_PATH        => $includepath,
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Includepath3.pm b/tags/0.31/t/lib/TestApp/View/TT/Includepath3.pm
new file mode 100644 (file)
index 0000000..ebadc34
--- /dev/null
@@ -0,0 +1,17 @@
+package TestApp::View::TT::Includepath3;
+
+use FindBin;
+use Path::Class;
+use strict;
+use base 'Catalyst::View::TT';
+
+our @include_path;
+my $includepath = dir($FindBin::Bin, '/lib/TestApp/root/test_include_path');
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+    INCLUDE_PATH        => \@include_path,
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Pkgconfig.pm b/tags/0.31/t/lib/TestApp/View/TT/Pkgconfig.pm
new file mode 100755 (executable)
index 0000000..011fab4
--- /dev/null
@@ -0,0 +1,12 @@
+package TestApp::View::TT::Pkgconfig;
+
+use strict;
+use base 'Catalyst::View::TT';
+
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/View/TT/Providerconfig.pm b/tags/0.31/t/lib/TestApp/View/TT/Providerconfig.pm
new file mode 100644 (file)
index 0000000..51b51c7
--- /dev/null
@@ -0,0 +1,22 @@
+package TestApp::View::TT::Providerconfig;
+
+use strict;
+use base 'Catalyst::View::TT';
+
+__PACKAGE__->config(
+    PRE_CHOMP          => 1,
+    POST_CHOMP         => 1,
+    TEMPLATE_EXTENSION => '.tt',
+    PROVIDERS           => [
+        {
+            name    => '+TestApp::FauxProvider',
+            args    => {}
+        },
+        # {
+        #     name    => '_file_',
+        #     args    => {}
+        # }
+    ]
+);
+
+1;
diff --git a/tags/0.31/t/lib/TestApp/root/specified_template.tt b/tags/0.31/t/lib/TestApp/root/specified_template.tt
new file mode 100644 (file)
index 0000000..d4e252f
--- /dev/null
@@ -0,0 +1 @@
+I should be a [% param %] test in [% name %]
diff --git a/tags/0.31/t/lib/TestApp/root/test.tt b/tags/0.31/t/lib/TestApp/root/test.tt
new file mode 100644 (file)
index 0000000..4a0a2d8
--- /dev/null
@@ -0,0 +1 @@
+[% message %]
diff --git a/tags/0.31/t/lib/TestApp/root/test_include_path/testpath.tt b/tags/0.31/t/lib/TestApp/root/test_include_path/testpath.tt
new file mode 100644 (file)
index 0000000..4a0a2d8
--- /dev/null
@@ -0,0 +1 @@
+[% message %]