added DBIx::Class schema "migration" script + test in generated_app.t
[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/;
d4655cdc 15use namespace::autoclean;
68ccb5e5 16
17my %cache;
18
19=head1 NAME
20
21Catalyst::Helper - Bootstrap a Catalyst application
22
23=head1 SYNOPSIS
24
fab70e0a 25 catalyst.pl <myappname>
68ccb5e5 26
27=cut
28
afd739f1 29sub get_sharedir_file {
30 my ($self, @filename) = @_;
76b106bc 31 my $dist_dir;
d7ebca0f 32 if (-d "inc/.author" && -f "lib/Catalyst/Helper.pm"
33 ) { # Can't use sharedir if we're in a checkout
34 # this feels horrible, better ideas?
76b106bc 35 $dist_dir = 'share';
36 }
37 else {
38 $dist_dir = dist_dir('Catalyst-Devel');
39 }
40 my $file = file( $dist_dir, @filename);
f8d3d4e0 41 Carp::confess("Cannot find $file") unless -r $file;
afd739f1 42 my $contents = $file->slurp;
43 return $contents;
44}
45
faae88e5 46# Do not touch this method, *EVER*, it is needed for back compat.
68ccb5e5 47sub get_file {
03082a71 48 my ( $self, $class, $file ) = @_;
49 unless ( $cache{$class} ) {
50 local $/;
51 $cache{$class} = eval "package $class; <DATA>";
52 }
53 my $data = $cache{$class};
0acedf59 54 Carp::confess("Could not get data from __DATA__ segment for $class")
55 unless $data;
03082a71 56 my @files = split /^__(.+)__\r?\n/m, $data;
57 shift @files;
58 while (@files) {
59 my ( $name, $content ) = splice @files, 0, 2;
60 return $content if $name eq $file;
61 }
62 return 0;
68ccb5e5 63}
64
03082a71 65
68ccb5e5 66sub mk_app {
67 my ( $self, $name ) = @_;
68
69 # Needs to be here for PAR
70 require Catalyst;
71
555cab18 72 if ( $name =~ /[^\w:]/ || $name =~ /^\d/ || $name =~ /\b:\b|:{3,}/) {
68ccb5e5 73 warn "Error: Invalid application name.\n";
74 return 0;
75 }
902763f2 76 $self->{name } = $name;
77 $self->{dir } = $name;
78 $self->{dir } =~ s/\:\:/-/g;
79 $self->{script } = File::Spec->catdir( $self->{dir}, 'script' );
80 $self->{appprefix } = Catalyst::Utils::appprefix($name);
e9345225 81 $self->{appenv } = Catalyst::Utils::class2env($name);
675fef06 82 $self->{startperl } = -r '/usr/bin/env'
83 ? '#!/usr/bin/env perl'
9bc8b354 84 : "#!$Config{perlpath} -w";
9ffb6b83 85 $self->{scriptgen } = $Catalyst::Devel::CATALYST_SCRIPT_GEN || 4;
902763f2 86 $self->{catalyst_version} = $Catalyst::VERSION;
87 $self->{author } = $self->{author} = $ENV{'AUTHOR'}
68ccb5e5 88 || eval { @{ [ getpwuid($<) ] }[6] }
89 || 'Catalyst developer';
90
91 my $gen_scripts = ( $self->{makefile} ) ? 0 : 1;
92 my $gen_makefile = ( $self->{scripts} ) ? 0 : 1;
93 my $gen_app = ( $self->{scripts} || $self->{makefile} ) ? 0 : 1;
94
95 if ($gen_app) {
96 $self->_mk_dirs;
97 $self->_mk_config;
98 $self->_mk_appclass;
99 $self->_mk_rootclass;
100 $self->_mk_readme;
101 $self->_mk_changes;
102 $self->_mk_apptest;
103 $self->_mk_images;
104 $self->_mk_favicon;
105 }
106 if ($gen_makefile) {
107 $self->_mk_makefile;
108 }
109 if ($gen_scripts) {
110 $self->_mk_cgi;
111 $self->_mk_fastcgi;
112 $self->_mk_server;
f5159e3e 113 $self->_mk_dbic_deploy;
68ccb5e5 114 $self->_mk_test;
115 $self->_mk_create;
45d74601 116 $self->_mk_information;
68ccb5e5 117 }
118 return $self->{dir};
119}
120
68ccb5e5 121sub mk_component {
122 my $self = shift;
123 my $app = shift;
124 $self->{app} = $app;
125 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
126 || eval { @{ [ getpwuid($<) ] }[6] }
127 || 'A clever guy';
128 $self->{base} ||= File::Spec->catdir( $FindBin::Bin, '..' );
129 unless ( $_[0] =~ /^(?:model|view|controller)$/i ) {
130 my $helper = shift;
131 my @args = @_;
132 my $class = "Catalyst::Helper::$helper";
133 eval "require $class";
134
135 if ($@) {
136 Catalyst::Exception->throw(
137 message => qq/Couldn't load helper "$class", "$@"/ );
138 }
139
140 if ( $class->can('mk_stuff') ) {
141 return 1 unless $class->mk_stuff( $self, @args );
142 }
143 }
144 else {
145 my $type = shift;
146 my $name = shift || "Missing name for model/view/controller";
147 my $helper = shift;
148 my @args = @_;
fab70e0a 149 return 0 if $name =~ /[^\w\:]/;
68ccb5e5 150 $type = lc $type;
151 $self->{long_type} = ucfirst $type;
152 $type = 'M' if $type =~ /model/i;
153 $type = 'V' if $type =~ /view/i;
154 $type = 'C' if $type =~ /controller/i;
155 my $appdir = File::Spec->catdir( split /\:\:/, $app );
156 my $test_path =
157 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, 'C' );
158 $type = $self->{long_type} unless -d $test_path;
159 $self->{type} = $type;
160 $self->{name} = $name;
161 $self->{class} = "$app\::$type\::$name";
162
163 # Class
164 my $path =
165 File::Spec->catdir( $FindBin::Bin, '..', 'lib', $appdir, $type );
166 my $file = $name;
167 if ( $name =~ /\:/ ) {
168 my @path = split /\:\:/, $name;
169 $file = pop @path;
170 $path = File::Spec->catdir( $path, @path );
171 }
172 $self->mk_dir($path);
173 $file = File::Spec->catfile( $path, "$file.pm" );
174 $self->{file} = $file;
175
176 # Test
177 $self->{test_dir} = File::Spec->catdir( $FindBin::Bin, '..', 't' );
178 $self->{test} = $self->next_test;
179
180 # Helper
181 if ($helper) {
182 my $comp = $self->{long_type};
183 my $class = "Catalyst::Helper::$comp\::$helper";
184 eval "require $class";
185
186 if ($@) {
187 Catalyst::Exception->throw(
188 message => qq/Couldn't load helper "$class", "$@"/ );
189 }
190
191 if ( $class->can('mk_compclass') ) {
192 return 1 unless $class->mk_compclass( $self, @args );
193 }
194 else { return 1 unless $self->_mk_compclass }
195
196 if ( $class->can('mk_comptest') ) {
197 $class->mk_comptest( $self, @args );
198 }
199 else { $self->_mk_comptest }
200 }
201
202 # Fallback
203 else {
204 return 1 unless $self->_mk_compclass;
205 $self->_mk_comptest;
206 }
207 }
208 return 1;
209}
210
68ccb5e5 211sub mk_dir {
212 my ( $self, $dir ) = @_;
213 if ( -d $dir ) {
214 print qq/ exists "$dir"\n/;
215 return 0;
216 }
217 if ( mkpath [$dir] ) {
218 print qq/created "$dir"\n/;
219 return 1;
220 }
221
222 Catalyst::Exception->throw( message => qq/Couldn't create "$dir", "$!"/ );
223}
224
68ccb5e5 225sub mk_file {
226 my ( $self, $file, $content ) = @_;
06f62452 227 if ( -e $file && -s _ ) {
68ccb5e5 228 print qq/ exists "$file"\n/;
229 return 0
230 unless ( $self->{'.newfiles'}
231 || $self->{scripts}
232 || $self->{makefile} );
233 if ( $self->{'.newfiles'} ) {
234 if ( my $f = IO::File->new("< $file") ) {
235 my $oldcontent = join( '', (<$f>) );
236 return 0 if $content eq $oldcontent;
237 }
238 $file .= '.new';
239 }
240 }
620dd287 241
68ccb5e5 242 if ( my $f = IO::File->new("> $file") ) {
243 binmode $f;
244 print $f $content;
245 print qq/created "$file"\n/;
246 return 1;
247 }
248
249 Catalyst::Exception->throw( message => qq/Couldn't create "$file", "$!"/ );
250}
251
68ccb5e5 252sub next_test {
253 my ( $self, $tname ) = @_;
254 if ($tname) { $tname = "$tname.t" }
255 else {
256 my $name = $self->{name};
257 my $prefix = $name;
258 $prefix =~ s/::/-/g;
259 $prefix = $prefix;
260 $tname = $prefix . '.t';
261 $self->{prefix} = $prefix;
262 $prefix = lc $prefix;
263 $prefix =~ s/-/\//g;
264 $self->{uri} = "/$prefix";
265 }
266 my $dir = $self->{test_dir};
267 my $type = lc $self->{type};
268 $self->mk_dir($dir);
269 return File::Spec->catfile( $dir, "$type\_$tname" );
270}
271
faae88e5 272# Do not touch this method, *EVER*, it is needed for back compat.
7025ed89 273## addendum: we had to split this method so we could have backwards
19fecc42 274## compatability. otherwise, we'd have no way to pass stuff from __DATA__
faae88e5 275
68ccb5e5 276sub render_file {
277 my ( $self, $file, $path, $vars ) = @_;
7025ed89 278 my $template = $self->get_file( ( caller(0) )[0], $file );
06f62452 279 $self->render_file_contents($template, $path, $vars);
7025ed89 280}
281
282sub render_sharedir_file {
283 my ( $self, $file, $path, $vars ) = @_;
284 my $template = $self->get_sharedir_file( $file );
f8d3d4e0 285 die("Cannot get template from $file for $self\n") unless $template;
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};
f8d3d4e0 446 return $self->render_sharedir_file( File::Spec->catfile('lib', 'Helper', 'compclass.pm.tt'), $file );
68ccb5e5 447}
448
449sub _mk_comptest {
450 my $self = shift;
451 my $test = $self->{test};
f8d3d4e0 452 $self->render_sharedir_file( File::Spec->catfile('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
f5159e3e 477sub _mk_dbic_deploy {
478 my $self = shift;
479 my $script = $self->{script};
480 my $appprefix = $self->{appprefix};
481 $self->render_sharedir_file( File::Spec->catfile('script', 'myapp_deploy_schema.pl.tt'), "$script\/$appprefix\_deploy_schema.pl" );
482 chmod 0700, "$script/$appprefix\_deploy_schema.pl";
483}
484
68ccb5e5 485sub _deprecate_file {
486 my ( $self, $file ) = @_;
487 if ( -e $file ) {
488 my $oldcontent;
489 if ( my $f = IO::File->new("< $file") ) {
490 $oldcontent = join( '', (<$f>) );
491 }
492 my $newfile = $file . '.deprecated';
493 if ( my $f = IO::File->new("> $newfile") ) {
494 binmode $f;
495 print $f $oldcontent;
496 print qq/created "$newfile"\n/;
497 unlink $file;
498 print qq/removed "$file"\n/;
499 return 1;
500 }
501 Catalyst::Exception->throw(
502 message => qq/Couldn't create "$file", "$!"/ );
503 }
504}
505
fab70e0a 506=head1 DESCRIPTION
507
508This module is used by B<catalyst.pl> to create a set of scripts for a
509new catalyst application. The scripts each contain documentation and
510will output help on how to use them if called incorrectly or in some
511cases, with no arguments.
512
513It also provides some useful methods for a Helper module to call when
514creating a component. See L</METHODS>.
515
516=head1 SCRIPTS
517
518=head2 _create.pl
519
520Used to create new components for a catalyst application at the
521development stage.
522
523=head2 _server.pl
524
525The catalyst test server, starts an HTTPD which outputs debugging to
526the terminal.
527
f5159e3e 528=head2 _deploy_dbic.pl
529
530Deploy a L<DBIx::Class> schema to the database of your choice.
531
fab70e0a 532=head2 _test.pl
533
534A script for running tests from the command-line.
535
536=head2 _cgi.pl
537
538Run your application as a CGI.
539
540=head2 _fastcgi.pl
541
542Run the application as a fastcgi app. Either by hand, or call this
543from FastCgiServer in your http server config.
544
68ccb5e5 545=head1 HELPERS
546
fab70e0a 547The L</_create.pl> script creates application components using Helper
548modules. The Catalyst team provides a good number of Helper modules
549for you to use. You can also add your own.
550
68ccb5e5 551Helpers are classes that provide two methods.
552
553 * mk_compclass - creates the Component class
554 * mk_comptest - creates the Component test
555
fab70e0a 556So when you call C<scripts/myapp_create.pl view MyView TT>, create
557will try to execute Catalyst::Helper::View::TT->mk_compclass and
68ccb5e5 558Catalyst::Helper::View::TT->mk_comptest.
559
c4c50c2d 560See L<Catalyst::Helper::View::TT> and
561L<Catalyst::Helper::Model::DBIC::Schema> for examples.
68ccb5e5 562
563All helper classes should be under one of the following namespaces.
564
565 Catalyst::Helper::Model::
566 Catalyst::Helper::View::
567 Catalyst::Helper::Controller::
568
675fef06 569=head2 COMMON HELPERS
bc8d7994 570
571=over
572
573=item *
574
575L<Catalyst::Helper::Model::DBIC::Schema> - DBIx::Class models
576
577=item *
578
579L<Catalyst::Helper::View::TT> - Template Toolkit view
580
581=item *
582
583L<Catalyst::Helper::Model::LDAP>
584
585=item *
586
587L<Catalyst::Helper::Model::Adaptor> - wrap any class into a Catalyst model
588
589=back
590
591=head3 NOTE
592
675fef06 593The helpers will read author name from /etc/passwd by default. + To override, please export the AUTHOR variable.
bc8d7994 594
595=head1 METHODS
596
fab70e0a 597=head2 mk_compclass
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<compclass>.
607
608=head2 mk_comptest
609
610This method in your Helper module is called with C<$helper>
611which is a L<Catalyst::Helper> object, and whichever other arguments
612the user added to the command-line. You can use the $helper to call methods
613described below.
614
615If the Helper module does not contain a C<mk_compclass> method, it
616will fall back to calling L</render_file>, with an argument of
617C<comptest>.
618
619=head2 mk_stuff
620
621This method is called if the user does not supply any of the usual
622component types C<view>, C<controller>, C<model>. It is passed the
623C<$helper> object (an instance of L<Catalyst::Helper>), and any other
624arguments the user typed.
625
626There is no fallback for this method.
627
bc8d7994 628=head1 INTERNAL METHODS
fab70e0a 629
630These are the methods that the Helper classes can call on the
631<$helper> object passed to them.
632
28eb1300 633=head2 render_file ($file, $path, $vars)
fab70e0a 634
28eb1300 635Render and create a file from a template in DATA using Template
636Toolkit. $file is the relevent chunk of the __DATA__ section, $path is
637the path to the file and $vars is the hashref as expected by
638L<Template Toolkit|Template>.
fab70e0a 639
28eb1300 640=head2 get_file ($class, $file)
fab70e0a 641
642Fetch file contents from the DATA section. This is used internally by
28eb1300 643L</render_file>. $class is the name of the class to get the DATA
644section from. __PACKAGE__ or ( caller(0) )[0] might be sensible
645values for this.
fab70e0a 646
647=head2 mk_app
648
649Create the main application skeleton. This is called by L<catalyst.pl>.
650
28eb1300 651=head2 mk_component ($app)
fab70e0a 652
653This method is called by L<create.pl> to make new components
654for your application.
655
28eb1300 656=head3 mk_dir ($path)
fab70e0a 657
658Surprisingly, this function makes a directory.
659
28eb1300 660=head2 mk_file ($file, $content)
fab70e0a 661
662Writes content to a file. Called by L</render_file>.
663
28eb1300 664=head2 next_test ($test_name)
fab70e0a 665
666Calculates the name of the next numbered test file and returns it.
28eb1300 667Don't give the number or the .t suffix for the test name.
fab70e0a 668
c6dbb300 669=cut
670
671=head2 get_sharedir_file
672
673Method for getting a file out of share/
674
675=cut
676
677=head2 render_file_contents
678
679Process a L<Template::Toolkit> template.
680
681=cut
682
683=head2 render_sharedir_file
684
685Render a template/image file from our share directory
686
687=cut
688
689
68ccb5e5 690=head1 NOTE
691
692The helpers will read author name from /etc/passwd by default.
693To override, please export the AUTHOR variable.
694
695=head1 SEE ALSO
696
697L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
698L<Catalyst::Response>, L<Catalyst>
699
f64c718c 700=head1 AUTHORS
68ccb5e5 701
f64c718c 702Catalyst Contributors, see Catalyst.pm
68ccb5e5 703
704=head1 LICENSE
705
7cd3b67e 706This library is free software. You can redistribute it and/or modify
68ccb5e5 707it under the same terms as Perl itself.
708
64d4433e 709=begin pod_to_ignore
710
68ccb5e5 711=cut
712
7131;
68ccb5e5 714