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