unfucked
[catagits/Catalyst-Devel.git] / lib / Catalyst / Helper.pm
CommitLineData
68ccb5e5 1package Catalyst::Helper;
d4655cdc 2use Moose;
68ccb5e5 3use Config;
4use File::Spec;
5use File::Path;
68ccb5e5 6use FindBin;
2415f774 7use IO::File;
8use POSIX 'strftime';
68ccb5e5 9use Template;
9ffb6b83 10use Catalyst::Devel;
68ccb5e5 11use Catalyst::Utils;
12use Catalyst::Exception;
afd739f1 13use Path::Class qw/dir file/;
14use File::ShareDir qw/dist_dir/;
239b5fc0 15use aliased 'Path::Class::Dir';
d4655cdc 16use namespace::autoclean;
68ccb5e5 17
18my %cache;
19
20=head1 NAME
21
22Catalyst::Helper - Bootstrap a Catalyst application
23
24=head1 SYNOPSIS
25
fab70e0a 26 catalyst.pl <myappname>
68ccb5e5 27
28=cut
29
faae88e5 30
31
afd739f1 32sub get_sharedir_file {
33 my ($self, @filename) = @_;
76b106bc 34 my $dist_dir;
d7ebca0f 35 if (-d "inc/.author" && -f "lib/Catalyst/Helper.pm"
36 ) { # Can't use sharedir if we're in a checkout
37 # this feels horrible, better ideas?
76b106bc 38 $dist_dir = 'share';
39 }
40 else {
41 $dist_dir = dist_dir('Catalyst-Devel');
42 }
43 my $file = file( $dist_dir, @filename);
afd739f1 44 my $contents = $file->slurp;
45 return $contents;
46}
47
faae88e5 48# Do not touch this method, *EVER*, it is needed for back compat.
68ccb5e5 49sub get_file {
03082a71 50 my ( $self, $class, $file ) = @_;
51 unless ( $cache{$class} ) {
52 local $/;
53 $cache{$class} = eval "package $class; <DATA>";
54 }
55 my $data = $cache{$class};
0acedf59 56 Carp::confess("Could not get data from __DATA__ segment for $class")
57 unless $data;
03082a71 58 my @files = split /^__(.+)__\r?\n/m, $data;
59 shift @files;
60 while (@files) {
61 my ( $name, $content ) = splice @files, 0, 2;
62 return $content if $name eq $file;
63 }
64 return 0;
68ccb5e5 65}
66
03082a71 67
68ccb5e5 68sub mk_app {
69 my ( $self, $name ) = @_;
70
71 # Needs to be here for PAR
72 require Catalyst;
73
555cab18 74 if ( $name =~ /[^\w:]/ || $name =~ /^\d/ || $name =~ /\b:\b|:{3,}/) {
68ccb5e5 75 warn "Error: Invalid application name.\n";
76 return 0;
77 }
902763f2 78 $self->{name } = $name;
79 $self->{dir } = $name;
80 $self->{dir } =~ s/\:\:/-/g;
81 $self->{script } = File::Spec->catdir( $self->{dir}, 'script' );
82 $self->{appprefix } = Catalyst::Utils::appprefix($name);
e9345225 83 $self->{appenv } = Catalyst::Utils::class2env($name);
675fef06 84 $self->{startperl } = -r '/usr/bin/env'
85 ? '#!/usr/bin/env perl'
9bc8b354 86 : "#!$Config{perlpath} -w";
9ffb6b83 87 $self->{scriptgen } = $Catalyst::Devel::CATALYST_SCRIPT_GEN || 4;
902763f2 88 $self->{catalyst_version} = $Catalyst::VERSION;
89 $self->{author } = $self->{author} = $ENV{'AUTHOR'}
68ccb5e5 90 || eval { @{ [ getpwuid($<) ] }[6] }
91 || 'Catalyst developer';
92
93 my $gen_scripts = ( $self->{makefile} ) ? 0 : 1;
94 my $gen_makefile = ( $self->{scripts} ) ? 0 : 1;
95 my $gen_app = ( $self->{scripts} || $self->{makefile} ) ? 0 : 1;
96
97 if ($gen_app) {
98 $self->_mk_dirs;
99 $self->_mk_config;
100 $self->_mk_appclass;
101 $self->_mk_rootclass;
102 $self->_mk_readme;
103 $self->_mk_changes;
104 $self->_mk_apptest;
105 $self->_mk_images;
106 $self->_mk_favicon;
107 }
108 if ($gen_makefile) {
109 $self->_mk_makefile;
110 }
111 if ($gen_scripts) {
112 $self->_mk_cgi;
113 $self->_mk_fastcgi;
114 $self->_mk_server;
115 $self->_mk_test;
116 $self->_mk_create;
45d74601 117 $self->_mk_information;
68ccb5e5 118 }
119 return $self->{dir};
120}
121
68ccb5e5 122sub mk_component {
123 my $self = shift;
124 my $app = shift;
125 $self->{app} = $app;
126 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
127 || eval { @{ [ getpwuid($<) ] }[6] }
128 || 'A clever guy';
129 $self->{base} ||= File::Spec->catdir( $FindBin::Bin, '..' );
130 unless ( $_[0] =~ /^(?:model|view|controller)$/i ) {
131 my $helper = shift;
132 my @args = @_;
133 my $class = "Catalyst::Helper::$helper";
134 eval "require $class";
135
136 if ($@) {
137 Catalyst::Exception->throw(
138 message => qq/Couldn't load helper "$class", "$@"/ );
139 }
140
141 if ( $class->can('mk_stuff') ) {
142 return 1 unless $class->mk_stuff( $self, @args );
143 }
144 }
145 else {
146 my $type = shift;
147 my $name = shift || "Missing name for model/view/controller";
148 my $helper = shift;
149 my @args = @_;
fab70e0a 150 return 0 if $name =~ /[^\w\:]/;
68ccb5e5 151 $type = lc $type;
152 $self->{long_type} = ucfirst $type;
153 $type = 'M' if $type =~ /model/i;
154 $type = 'V' if $type =~ /view/i;
155 $type = 'C' if $type =~ /controller/i;
156 my $appdir = File::Spec->catdir( split /\:\:/, $app );
157 my $test_path =
158 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, 'C' );
159 $type = $self->{long_type} unless -d $test_path;
160 $self->{type} = $type;
161 $self->{name} = $name;
162 $self->{class} = "$app\::$type\::$name";
163
164 # Class
165 my $path =
166 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, $type );
167 my $file = $name;
168 if ( $name =~ /\:/ ) {
169 my @path = split /\:\:/, $name;
170 $file = pop @path;
171 $path = File::Spec->catdir( $path, @path );
172 }
173 $self->mk_dir($path);
174 $file = File::Spec->catfile( $path, "$file.pm" );
175 $self->{file} = $file;
176
177 # Test
178 $self->{test_dir} = File::Spec->catdir( $FindBin::Bin, '..', 't' );
179 $self->{test} = $self->next_test;
180
181 # Helper
182 if ($helper) {
183 my $comp = $self->{long_type};
184 my $class = "Catalyst::Helper::$comp\::$helper";
185 eval "require $class";
186
187 if ($@) {
188 Catalyst::Exception->throw(
189 message => qq/Couldn't load helper "$class", "$@"/ );
190 }
191
192 if ( $class->can('mk_compclass') ) {
193 return 1 unless $class->mk_compclass( $self, @args );
194 }
195 else { return 1 unless $self->_mk_compclass }
196
197 if ( $class->can('mk_comptest') ) {
198 $class->mk_comptest( $self, @args );
199 }
200 else { $self->_mk_comptest }
201 }
202
203 # Fallback
204 else {
205 return 1 unless $self->_mk_compclass;
206 $self->_mk_comptest;
207 }
208 }
209 return 1;
210}
211
68ccb5e5 212sub mk_dir {
213 my ( $self, $dir ) = @_;
214 if ( -d $dir ) {
215 print qq/ exists "$dir"\n/;
216 return 0;
217 }
218 if ( mkpath [$dir] ) {
219 print qq/created "$dir"\n/;
220 return 1;
221 }
222
223 Catalyst::Exception->throw( message => qq/Couldn't create "$dir", "$!"/ );
224}
225
68ccb5e5 226sub mk_file {
227 my ( $self, $file, $content ) = @_;
06f62452 228 if ( -e $file && -s _ ) {
68ccb5e5 229 print qq/ exists "$file"\n/;
230 return 0
231 unless ( $self->{'.newfiles'}
232 || $self->{scripts}
233 || $self->{makefile} );
234 if ( $self->{'.newfiles'} ) {
235 if ( my $f = IO::File->new("< $file") ) {
236 my $oldcontent = join( '', (<$f>) );
237 return 0 if $content eq $oldcontent;
238 }
239 $file .= '.new';
240 }
241 }
620dd287 242
68ccb5e5 243 if ( my $f = IO::File->new("> $file") ) {
244 binmode $f;
245 print $f $content;
246 print qq/created "$file"\n/;
247 return 1;
248 }
249
250 Catalyst::Exception->throw( message => qq/Couldn't create "$file", "$!"/ );
251}
252
68ccb5e5 253sub next_test {
254 my ( $self, $tname ) = @_;
255 if ($tname) { $tname = "$tname.t" }
256 else {
257 my $name = $self->{name};
258 my $prefix = $name;
259 $prefix =~ s/::/-/g;
260 $prefix = $prefix;
261 $tname = $prefix . '.t';
262 $self->{prefix} = $prefix;
263 $prefix = lc $prefix;
264 $prefix =~ s/-/\//g;
265 $self->{uri} = "/$prefix";
266 }
267 my $dir = $self->{test_dir};
268 my $type = lc $self->{type};
269 $self->mk_dir($dir);
270 return File::Spec->catfile( $dir, "$type\_$tname" );
271}
272
faae88e5 273# Do not touch this method, *EVER*, it is needed for back compat.
7025ed89 274## addendum: we had to split this method so we could have backwards
19fecc42 275## compatability. otherwise, we'd have no way to pass stuff from __DATA__
faae88e5 276
68ccb5e5 277sub render_file {
278 my ( $self, $file, $path, $vars ) = @_;
7025ed89 279 my $template = $self->get_file( ( caller(0) )[0], $file );
06f62452 280 $self->render_file_contents($template, $path, $vars);
7025ed89 281}
282
283sub render_sharedir_file {
284 my ( $self, $file, $path, $vars ) = @_;
285 my $template = $self->get_sharedir_file( $file );
e97273a4 286 $self->render_file_contents($template, $path, $vars);
7025ed89 287}
288
289sub render_file_contents {
290 my ( $self, $template, $path, $vars ) = @_;
68ccb5e5 291 $vars ||= {};
292 my $t = Template->new;
68ccb5e5 293 return 0 unless $template;
294 my $output;
295 $t->process( \$template, { %{$self}, %$vars }, \$output )
296 || Catalyst::Exception->throw(
7025ed89 297 message => qq/Couldn't process "$template", / . $t->error() );
68ccb5e5 298 $self->mk_file( $path, $output );
299}
300
45d74601 301sub _mk_information {
302 my $self = shift;
303 print qq/Change to application directory and Run "perl Makefile.PL" to make sure your install is complete\n/;
304}
305
68ccb5e5 306sub _mk_dirs {
307 my $self = shift;
308 $self->mk_dir( $self->{dir} );
309 $self->mk_dir( $self->{script} );
310 $self->{lib} = File::Spec->catdir( $self->{dir}, 'lib' );
311 $self->mk_dir( $self->{lib} );
312 $self->{root} = File::Spec->catdir( $self->{dir}, 'root' );
313 $self->mk_dir( $self->{root} );
314 $self->{static} = File::Spec->catdir( $self->{root}, 'static' );
315 $self->mk_dir( $self->{static} );
316 $self->{images} = File::Spec->catdir( $self->{static}, 'images' );
317 $self->mk_dir( $self->{images} );
318 $self->{t} = File::Spec->catdir( $self->{dir}, 't' );
319 $self->mk_dir( $self->{t} );
320
321 $self->{class} = File::Spec->catdir( split( /\:\:/, $self->{name} ) );
322 $self->{mod} = File::Spec->catdir( $self->{lib}, $self->{class} );
323 $self->mk_dir( $self->{mod} );
324
325 if ( $self->{short} ) {
326 $self->{m} = File::Spec->catdir( $self->{mod}, 'M' );
327 $self->mk_dir( $self->{m} );
328 $self->{v} = File::Spec->catdir( $self->{mod}, 'V' );
329 $self->mk_dir( $self->{v} );
330 $self->{c} = File::Spec->catdir( $self->{mod}, 'C' );
331 $self->mk_dir( $self->{c} );
332 }
333 else {
334 $self->{m} = File::Spec->catdir( $self->{mod}, 'Model' );
335 $self->mk_dir( $self->{m} );
336 $self->{v} = File::Spec->catdir( $self->{mod}, 'View' );
337 $self->mk_dir( $self->{v} );
338 $self->{c} = File::Spec->catdir( $self->{mod}, 'Controller' );
339 $self->mk_dir( $self->{c} );
340 }
341 my $name = $self->{name};
342 $self->{rootname} =
343 $self->{short} ? "$name\::C::Root" : "$name\::Controller::Root";
344 $self->{base} = File::Spec->rel2abs( $self->{dir} );
345}
346
347sub _mk_appclass {
348 my $self = shift;
349 my $mod = $self->{mod};
c485fb09 350 $self->render_sharedir_file( File::Spec->catfile('lib', 'MyApp.pm.tt'), "$mod.pm" );
68ccb5e5 351}
352
353sub _mk_rootclass {
354 my $self = shift;
c485fb09 355 $self->render_sharedir_file( File::Spec->catfile('lib', 'MyApp', 'Controller', 'Root.pm.tt'),
68ccb5e5 356 File::Spec->catfile( $self->{c}, "Root.pm" ) );
357}
358
359sub _mk_makefile {
360 my $self = shift;
361 $self->{path} = File::Spec->catfile( 'lib', split( '::', $self->{name} ) );
362 $self->{path} .= '.pm';
363 my $dir = $self->{dir};
d5ff5c0f 364 $self->render_sharedir_file( 'Makefile.PL.tt', "$dir\/Makefile.PL" );
68ccb5e5 365
366 if ( $self->{makefile} ) {
367
368 # deprecate the old Build.PL file when regenerating Makefile.PL
369 $self->_deprecate_file(
370 File::Spec->catdir( $self->{dir}, 'Build.PL' ) );
371 }
372}
373
374sub _mk_config {
375 my $self = shift;
376 my $dir = $self->{dir};
377 my $appprefix = $self->{appprefix};
d5ff5c0f 378 $self->render_sharedir_file( 'myapp.conf.tt',
a4e6d745 379 File::Spec->catfile( $dir, "$appprefix.conf" ) );
68ccb5e5 380}
381
382sub _mk_readme {
383 my $self = shift;
384 my $dir = $self->{dir};
d5ff5c0f 385 $self->render_sharedir_file( 'README.tt', "$dir\/README" );
68ccb5e5 386}
387
388sub _mk_changes {
389 my $self = shift;
390 my $dir = $self->{dir};
5b1ec88b 391 my $time = strftime('%Y-%m-%d %H:%M:%S', localtime time);
d5ff5c0f 392 $self->render_sharedir_file( 'Changes.tt', "$dir\/Changes", { time => $time } );
68ccb5e5 393}
394
395sub _mk_apptest {
396 my $self = shift;
397 my $t = $self->{t};
c485fb09 398 $self->render_sharedir_file( File::Spec->catfile('t', '01app.t.tt'), "$t\/01app.t" );
399 $self->render_sharedir_file( File::Spec->catfile('t', '02pod.t.tt'), "$t\/02pod.t" );
400 $self->render_sharedir_file( File::Spec->catfile('t', '03podcoverage.t.tt'), "$t\/03podcoverage.t" );
68ccb5e5 401}
402
403sub _mk_cgi {
404 my $self = shift;
405 my $script = $self->{script};
406 my $appprefix = $self->{appprefix};
c485fb09 407 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_cgi.pl.tt'), "$script\/$appprefix\_cgi.pl" );
68ccb5e5 408 chmod 0700, "$script/$appprefix\_cgi.pl";
409}
410
411sub _mk_fastcgi {
412 my $self = shift;
413 my $script = $self->{script};
414 my $appprefix = $self->{appprefix};
c485fb09 415 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_fastcgi.pl.tt'), "$script\/$appprefix\_fastcgi.pl" );
68ccb5e5 416 chmod 0700, "$script/$appprefix\_fastcgi.pl";
417}
418
419sub _mk_server {
420 my $self = shift;
421 my $script = $self->{script};
422 my $appprefix = $self->{appprefix};
c485fb09 423 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_server.pl.tt'), "$script\/$appprefix\_server.pl" );
68ccb5e5 424 chmod 0700, "$script/$appprefix\_server.pl";
425}
426
427sub _mk_test {
428 my $self = shift;
429 my $script = $self->{script};
430 my $appprefix = $self->{appprefix};
c485fb09 431 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_test.pl.tt'), "$script/$appprefix\_test.pl" );
68ccb5e5 432 chmod 0700, "$script/$appprefix\_test.pl";
433}
434
435sub _mk_create {
436 my $self = shift;
437 my $script = $self->{script};
438 my $appprefix = $self->{appprefix};
c485fb09 439 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_create.pl.tt'), "$script\/$appprefix\_create.pl" );
68ccb5e5 440 chmod 0700, "$script/$appprefix\_create.pl";
441}
442
443sub _mk_compclass {
444 my $self = shift;
445 my $file = $self->{file};
620dd287 446 return $self->render_sharedir_file( 'lib', 'Helper', 'compclass.tt', "$file" );
68ccb5e5 447}
448
449sub _mk_comptest {
450 my $self = shift;
451 my $test = $self->{test};
76a155bc 452 $self->render_sharedir_file( 't', 'comptest.tt', "$test" ); ## wtf do i rename this to?
68ccb5e5 453}
454
455sub _mk_images {
456 my $self = shift;
457 my $images = $self->{images};
458 my @images =
459 qw/catalyst_logo btn_120x50_built btn_120x50_built_shadow
460 btn_120x50_powered btn_120x50_powered_shadow btn_88x31_built
461 btn_88x31_built_shadow btn_88x31_powered btn_88x31_powered_shadow/;
462 for my $name (@images) {
3f2f19ec 463 my $image = $self->get_sharedir_file("root", "static", "images", "$name.png.bin");
68ccb5e5 464 $self->mk_file( File::Spec->catfile( $images, "$name.png" ), $image );
465 }
466}
467
468sub _mk_favicon {
469 my $self = shift;
470 my $root = $self->{root};
f023d4a1 471 my $favicon = $self->get_sharedir_file( 'root', 'favicon.ico.bin' );
afd739f1 472 my $dest = File::Spec->catfile( $root, "favicon.ico" );
473 $self->mk_file( $dest, $favicon );
68ccb5e5 474
475}
476
477sub _deprecate_file {
478 my ( $self, $file ) = @_;
479 if ( -e $file ) {
480 my $oldcontent;
481 if ( my $f = IO::File->new("< $file") ) {
482 $oldcontent = join( '', (<$f>) );
483 }
484 my $newfile = $file . '.deprecated';
485 if ( my $f = IO::File->new("> $newfile") ) {
486 binmode $f;
487 print $f $oldcontent;
488 print qq/created "$newfile"\n/;
489 unlink $file;
490 print qq/removed "$file"\n/;
491 return 1;
492 }
493 Catalyst::Exception->throw(
494 message => qq/Couldn't create "$file", "$!"/ );
495 }
496}
497
239b5fc0 498
fab70e0a 499=head1 DESCRIPTION
500
501This module is used by B<catalyst.pl> to create a set of scripts for a
502new catalyst application. The scripts each contain documentation and
503will output help on how to use them if called incorrectly or in some
504cases, with no arguments.
505
506It also provides some useful methods for a Helper module to call when
507creating a component. See L</METHODS>.
508
509=head1 SCRIPTS
510
511=head2 _create.pl
512
513Used to create new components for a catalyst application at the
514development stage.
515
516=head2 _server.pl
517
518The catalyst test server, starts an HTTPD which outputs debugging to
519the terminal.
520
521=head2 _test.pl
522
523A script for running tests from the command-line.
524
525=head2 _cgi.pl
526
527Run your application as a CGI.
528
529=head2 _fastcgi.pl
530
531Run the application as a fastcgi app. Either by hand, or call this
532from FastCgiServer in your http server config.
533
68ccb5e5 534=head1 HELPERS
535
fab70e0a 536The L</_create.pl> script creates application components using Helper
537modules. The Catalyst team provides a good number of Helper modules
538for you to use. You can also add your own.
539
68ccb5e5 540Helpers are classes that provide two methods.
541
542 * mk_compclass - creates the Component class
543 * mk_comptest - creates the Component test
544
fab70e0a 545So when you call C<scripts/myapp_create.pl view MyView TT>, create
546will try to execute Catalyst::Helper::View::TT->mk_compclass and
68ccb5e5 547Catalyst::Helper::View::TT->mk_comptest.
548
c4c50c2d 549See L<Catalyst::Helper::View::TT> and
550L<Catalyst::Helper::Model::DBIC::Schema> for examples.
68ccb5e5 551
552All helper classes should be under one of the following namespaces.
553
554 Catalyst::Helper::Model::
555 Catalyst::Helper::View::
556 Catalyst::Helper::Controller::
557
675fef06 558=head2 COMMON HELPERS
bc8d7994 559
560=over
561
562=item *
563
564L<Catalyst::Helper::Model::DBIC::Schema> - DBIx::Class models
565
566=item *
567
568L<Catalyst::Helper::View::TT> - Template Toolkit view
569
570=item *
571
572L<Catalyst::Helper::Model::LDAP>
573
574=item *
575
576L<Catalyst::Helper::Model::Adaptor> - wrap any class into a Catalyst model
577
578=back
579
580=head3 NOTE
581
675fef06 582The helpers will read author name from /etc/passwd by default. + To override, please export the AUTHOR variable.
bc8d7994 583
584=head1 METHODS
585
fab70e0a 586=head2 mk_compclass
587
588This method in your Helper module is called with C<$helper>
589which is a L<Catalyst::Helper> object, and whichever other arguments
590the user added to the command-line. You can use the $helper to call methods
591described below.
592
593If the Helper module does not contain a C<mk_compclass> method, it
594will fall back to calling L</render_file>, with an argument of
595C<compclass>.
596
597=head2 mk_comptest
598
599This method in your Helper module is called with C<$helper>
600which is a L<Catalyst::Helper> object, and whichever other arguments
601the user added to the command-line. You can use the $helper to call methods
602described below.
603
604If the Helper module does not contain a C<mk_compclass> method, it
605will fall back to calling L</render_file>, with an argument of
606C<comptest>.
607
608=head2 mk_stuff
609
610This method is called if the user does not supply any of the usual
611component types C<view>, C<controller>, C<model>. It is passed the
612C<$helper> object (an instance of L<Catalyst::Helper>), and any other
613arguments the user typed.
614
615There is no fallback for this method.
616
bc8d7994 617=head1 INTERNAL METHODS
fab70e0a 618
619These are the methods that the Helper classes can call on the
620<$helper> object passed to them.
621
28eb1300 622=head2 render_file ($file, $path, $vars)
fab70e0a 623
28eb1300 624Render and create a file from a template in DATA using Template
625Toolkit. $file is the relevent chunk of the __DATA__ section, $path is
626the path to the file and $vars is the hashref as expected by
627L<Template Toolkit|Template>.
fab70e0a 628
28eb1300 629=head2 get_file ($class, $file)
fab70e0a 630
631Fetch file contents from the DATA section. This is used internally by
28eb1300 632L</render_file>. $class is the name of the class to get the DATA
633section from. __PACKAGE__ or ( caller(0) )[0] might be sensible
634values for this.
fab70e0a 635
636=head2 mk_app
637
638Create the main application skeleton. This is called by L<catalyst.pl>.
639
28eb1300 640=head2 mk_component ($app)
fab70e0a 641
642This method is called by L<create.pl> to make new components
643for your application.
644
28eb1300 645=head3 mk_dir ($path)
fab70e0a 646
647Surprisingly, this function makes a directory.
648
28eb1300 649=head2 mk_file ($file, $content)
fab70e0a 650
651Writes content to a file. Called by L</render_file>.
652
28eb1300 653=head2 next_test ($test_name)
fab70e0a 654
655Calculates the name of the next numbered test file and returns it.
28eb1300 656Don't give the number or the .t suffix for the test name.
fab70e0a 657
c6dbb300 658=head2 Dir
659
660Alias for L<Path::Class::Dir>
661
662=cut
663
664=head2 get_sharedir_file
665
666Method for getting a file out of share/
667
668=cut
669
670=head2 render_file_contents
671
672Process a L<Template::Toolkit> template.
673
674=cut
675
676=head2 render_sharedir_file
677
678Render a template/image file from our share directory
679
680=cut
681
682
68ccb5e5 683=head1 NOTE
684
685The helpers will read author name from /etc/passwd by default.
686To override, please export the AUTHOR variable.
687
688=head1 SEE ALSO
689
690L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
691L<Catalyst::Response>, L<Catalyst>
692
f64c718c 693=head1 AUTHORS
68ccb5e5 694
f64c718c 695Catalyst Contributors, see Catalyst.pm
68ccb5e5 696
697=head1 LICENSE
698
7cd3b67e 699This library is free software. You can redistribute it and/or modify
68ccb5e5 700it under the same terms as Perl itself.
701
64d4433e 702=begin pod_to_ignore
703
68ccb5e5 704=cut
705
7061;
68ccb5e5 707