No, it needs to be left so that other components outside devel still work
[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
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
afd739f1 30sub get_sharedir_file {
31 my ($self, @filename) = @_;
76b106bc 32 my $dist_dir;
d7ebca0f 33 if (-d "inc/.author" && -f "lib/Catalyst/Helper.pm"
34 ) { # Can't use sharedir if we're in a checkout
35 # this feels horrible, better ideas?
76b106bc 36 $dist_dir = 'share';
37 }
38 else {
39 $dist_dir = dist_dir('Catalyst-Devel');
40 }
41 my $file = file( $dist_dir, @filename);
f8d3d4e0 42 Carp::confess("Cannot find $file") unless -r $file;
afd739f1 43 my $contents = $file->slurp;
44 return $contents;
45}
46
faae88e5 47# Do not touch this method, *EVER*, it is needed for back compat.
68ccb5e5 48sub get_file {
03082a71 49 my ( $self, $class, $file ) = @_;
50 unless ( $cache{$class} ) {
51 local $/;
52 $cache{$class} = eval "package $class; <DATA>";
53 }
54 my $data = $cache{$class};
0acedf59 55 Carp::confess("Could not get data from __DATA__ segment for $class")
56 unless $data;
03082a71 57 my @files = split /^__(.+)__\r?\n/m, $data;
58 shift @files;
59 while (@files) {
60 my ( $name, $content ) = splice @files, 0, 2;
61 return $content if $name eq $file;
62 }
63 return 0;
68ccb5e5 64}
65
03082a71 66
68ccb5e5 67sub mk_app {
68 my ( $self, $name ) = @_;
69
70 # Needs to be here for PAR
71 require Catalyst;
72
555cab18 73 if ( $name =~ /[^\w:]/ || $name =~ /^\d/ || $name =~ /\b:\b|:{3,}/) {
68ccb5e5 74 warn "Error: Invalid application name.\n";
75 return 0;
76 }
902763f2 77 $self->{name } = $name;
78 $self->{dir } = $name;
79 $self->{dir } =~ s/\:\:/-/g;
068587bd 80 $self->{script } = dir( $self->{dir}, 'script' );
902763f2 81 $self->{appprefix } = Catalyst::Utils::appprefix($name);
e9345225 82 $self->{appenv } = Catalyst::Utils::class2env($name);
675fef06 83 $self->{startperl } = -r '/usr/bin/env'
84 ? '#!/usr/bin/env perl'
9bc8b354 85 : "#!$Config{perlpath} -w";
2ad36447 86 $self->{scriptgen } = $Catalyst::Devel::CATALYST_SCRIPT_GEN;
902763f2 87 $self->{catalyst_version} = $Catalyst::VERSION;
88 $self->{author } = $self->{author} = $ENV{'AUTHOR'}
68ccb5e5 89 || eval { @{ [ getpwuid($<) ] }[6] }
90 || 'Catalyst developer';
91
92 my $gen_scripts = ( $self->{makefile} ) ? 0 : 1;
93 my $gen_makefile = ( $self->{scripts} ) ? 0 : 1;
94 my $gen_app = ( $self->{scripts} || $self->{makefile} ) ? 0 : 1;
95
96 if ($gen_app) {
420ad692 97 for ( qw/ _mk_dirs _mk_config _mk_appclass _mk_rootclass _mk_readme
98 _mk_changes _mk_apptest _mk_images _mk_favicon/ ) {
99
100 $self->$_;
420ad692 101 }
68ccb5e5 102 }
103 if ($gen_makefile) {
104 $self->_mk_makefile;
105 }
106 if ($gen_scripts) {
420ad692 107 for ( qw/ _mk_cgi _mk_fastcgi _mk_server
28d172c6 108 _mk_test _mk_create _mk_information
109 / ) {
110 $self->$_;
111 }
68ccb5e5 112 }
113 return $self->{dir};
114}
115
23f9f145 116## not much of this can really be changed, mk_compclass must be left for
117## backcompat
68ccb5e5 118sub mk_component {
119 my $self = shift;
120 my $app = shift;
121 $self->{app} = $app;
122 $self->{author} = $self->{author} = $ENV{'AUTHOR'}
123 || eval { @{ [ getpwuid($<) ] }[6] }
124 || 'A clever guy';
068587bd 125 $self->{base} ||= dir( $FindBin::Bin, '..' );
68ccb5e5 126 unless ( $_[0] =~ /^(?:model|view|controller)$/i ) {
127 my $helper = shift;
128 my @args = @_;
129 my $class = "Catalyst::Helper::$helper";
130 eval "require $class";
131
132 if ($@) {
133 Catalyst::Exception->throw(
134 message => qq/Couldn't load helper "$class", "$@"/ );
135 }
136
137 if ( $class->can('mk_stuff') ) {
138 return 1 unless $class->mk_stuff( $self, @args );
139 }
140 }
141 else {
142 my $type = shift;
143 my $name = shift || "Missing name for model/view/controller";
144 my $helper = shift;
145 my @args = @_;
fab70e0a 146 return 0 if $name =~ /[^\w\:]/;
68ccb5e5 147 $type = lc $type;
148 $self->{long_type} = ucfirst $type;
149 $type = 'M' if $type =~ /model/i;
150 $type = 'V' if $type =~ /view/i;
151 $type = 'C' if $type =~ /controller/i;
068587bd 152 my $appdir = dir( split /\:\:/, $app );
68ccb5e5 153 my $test_path =
068587bd 154 dir( $self->{base}, 'lib', $appdir, 'C' );
68ccb5e5 155 $type = $self->{long_type} unless -d $test_path;
156 $self->{type} = $type;
157 $self->{name} = $name;
158 $self->{class} = "$app\::$type\::$name";
159
160 # Class
161 my $path =
068587bd 162 dir( $self->{base}, 'lib', $appdir, $type );
68ccb5e5 163 my $file = $name;
164 if ( $name =~ /\:/ ) {
165 my @path = split /\:\:/, $name;
166 $file = pop @path;
068587bd 167 $path = dir( $path, @path );
68ccb5e5 168 }
169 $self->mk_dir($path);
068587bd 170 $file = file( $path, "$file.pm" );
68ccb5e5 171 $self->{file} = $file;
172
173 # Test
068587bd 174 $self->{test_dir} = dir( $self->{base}, 't' );
68ccb5e5 175 $self->{test} = $self->next_test;
176
177 # Helper
178 if ($helper) {
179 my $comp = $self->{long_type};
180 my $class = "Catalyst::Helper::$comp\::$helper";
181 eval "require $class";
182
183 if ($@) {
184 Catalyst::Exception->throw(
185 message => qq/Couldn't load helper "$class", "$@"/ );
186 }
187
188 if ( $class->can('mk_compclass') ) {
189 return 1 unless $class->mk_compclass( $self, @args );
190 }
20755aa7 191 else {
192 return 1 unless $self->_mk_compclass
193 }
68ccb5e5 194
195 if ( $class->can('mk_comptest') ) {
196 $class->mk_comptest( $self, @args );
197 }
20755aa7 198 else {
199 $self->_mk_comptest
200 }
68ccb5e5 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);
068587bd 270 return file( $dir, "$type\_$tname" );
68ccb5e5 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 );
f8d3d4e0 286 die("Cannot get template from $file for $self\n") unless $template;
e97273a4 287 $self->render_file_contents($template, $path, $vars);
7025ed89 288}
289
290sub render_file_contents {
291 my ( $self, $template, $path, $vars ) = @_;
68ccb5e5 292 $vars ||= {};
293 my $t = Template->new;
68ccb5e5 294 return 0 unless $template;
295 my $output;
296 $t->process( \$template, { %{$self}, %$vars }, \$output )
297 || Catalyst::Exception->throw(
7025ed89 298 message => qq/Couldn't process "$template", / . $t->error() );
68ccb5e5 299 $self->mk_file( $path, $output );
300}
301
45d74601 302sub _mk_information {
303 my $self = shift;
304 print qq/Change to application directory and Run "perl Makefile.PL" to make sure your install is complete\n/;
305}
306
68ccb5e5 307sub _mk_dirs {
308 my $self = shift;
309 $self->mk_dir( $self->{dir} );
310 $self->mk_dir( $self->{script} );
068587bd 311 $self->{lib} = dir( $self->{dir}, 'lib' );
68ccb5e5 312 $self->mk_dir( $self->{lib} );
068587bd 313 $self->{root} = dir( $self->{dir}, 'root' );
68ccb5e5 314 $self->mk_dir( $self->{root} );
068587bd 315 $self->{static} = dir( $self->{root}, 'static' );
68ccb5e5 316 $self->mk_dir( $self->{static} );
068587bd 317 $self->{images} = dir( $self->{static}, 'images' );
68ccb5e5 318 $self->mk_dir( $self->{images} );
068587bd 319 $self->{t} = dir( $self->{dir}, 't' );
68ccb5e5 320 $self->mk_dir( $self->{t} );
321
068587bd 322 $self->{class} = dir( split( /\:\:/, $self->{name} ) );
323 $self->{mod} = dir( $self->{lib}, $self->{class} );
68ccb5e5 324 $self->mk_dir( $self->{mod} );
325
326 if ( $self->{short} ) {
068587bd 327 $self->{m} = dir( $self->{mod}, 'M' );
68ccb5e5 328 $self->mk_dir( $self->{m} );
068587bd 329 $self->{v} = dir( $self->{mod}, 'V' );
68ccb5e5 330 $self->mk_dir( $self->{v} );
068587bd 331 $self->{c} = dir( $self->{mod}, 'C' );
68ccb5e5 332 $self->mk_dir( $self->{c} );
333 }
334 else {
068587bd 335 $self->{m} = dir( $self->{mod}, 'Model' );
68ccb5e5 336 $self->mk_dir( $self->{m} );
068587bd 337 $self->{v} = dir( $self->{mod}, 'View' );
68ccb5e5 338 $self->mk_dir( $self->{v} );
068587bd 339 $self->{c} = dir( $self->{mod}, 'Controller' );
68ccb5e5 340 $self->mk_dir( $self->{c} );
341 }
342 my $name = $self->{name};
343 $self->{rootname} =
344 $self->{short} ? "$name\::C::Root" : "$name\::Controller::Root";
068587bd 345 $self->{base} = dir( $self->{dir} )->absolute;
68ccb5e5 346}
347
348sub _mk_appclass {
349 my $self = shift;
350 my $mod = $self->{mod};
068587bd 351 $self->render_sharedir_file( file('lib', 'MyApp.pm.tt'), "$mod.pm" );
68ccb5e5 352}
353
354sub _mk_rootclass {
355 my $self = shift;
068587bd 356 $self->render_sharedir_file( file('lib', 'MyApp', 'Controller', 'Root.pm.tt'),
357 file( $self->{c}, "Root.pm" ) );
68ccb5e5 358}
359
360sub _mk_makefile {
361 my $self = shift;
068587bd 362 $self->{path} = dir( 'lib', split( '::', $self->{name} ) );
68ccb5e5 363 $self->{path} .= '.pm';
364 my $dir = $self->{dir};
068587bd 365 $self->render_sharedir_file( 'Makefile.PL.tt', file($dir, "Makefile.PL") );
68ccb5e5 366
367 if ( $self->{makefile} ) {
368
369 # deprecate the old Build.PL file when regenerating Makefile.PL
370 $self->_deprecate_file(
068587bd 371 file( $self->{dir}, 'Build.PL' ) );
68ccb5e5 372 }
373}
374
375sub _mk_config {
376 my $self = shift;
377 my $dir = $self->{dir};
378 my $appprefix = $self->{appprefix};
d5ff5c0f 379 $self->render_sharedir_file( 'myapp.conf.tt',
068587bd 380 file( $dir, "$appprefix.conf" ) );
68ccb5e5 381}
382
383sub _mk_readme {
384 my $self = shift;
385 my $dir = $self->{dir};
068587bd 386 $self->render_sharedir_file( 'README.tt', file($dir, "README") );
68ccb5e5 387}
388
389sub _mk_changes {
390 my $self = shift;
391 my $dir = $self->{dir};
5b1ec88b 392 my $time = strftime('%Y-%m-%d %H:%M:%S', localtime time);
957ccd4d 393 $self->render_sharedir_file( 'Changes.tt', file($dir, "Changes"), { time => $time } );
68ccb5e5 394}
395
396sub _mk_apptest {
397 my $self = shift;
398 my $t = $self->{t};
068587bd 399 $self->render_sharedir_file( file('t', '01app.t.tt'), file($t, "01app.t") );
400 $self->render_sharedir_file( file('t', '02pod.t.tt'), file($t, "02pod.t") );
401 $self->render_sharedir_file( file('t', '03podcoverage.t.tt'), file($t, "03podcoverage.t") );
68ccb5e5 402}
403
404sub _mk_cgi {
405 my $self = shift;
406 my $script = $self->{script};
407 my $appprefix = $self->{appprefix};
068587bd 408 $self->render_sharedir_file( file('script', 'myapp_cgi.pl.tt'), file($script,"$appprefix\_cgi.pl") );
409 chmod 0700, file($script,"$appprefix\_cgi.pl");
68ccb5e5 410}
411
412sub _mk_fastcgi {
413 my $self = shift;
414 my $script = $self->{script};
415 my $appprefix = $self->{appprefix};
068587bd 416 $self->render_sharedir_file( file('script', 'myapp_fastcgi.pl.tt'), file($script, "$appprefix\_fastcgi.pl") );
417 chmod 0700, file($script, "$appprefix\_fastcgi.pl");
68ccb5e5 418}
419
420sub _mk_server {
421 my $self = shift;
422 my $script = $self->{script};
423 my $appprefix = $self->{appprefix};
068587bd 424 $self->render_sharedir_file( file('script', 'myapp_server.pl.tt'), file($script, "$appprefix\_server.pl") );
425 chmod 0700, file($script, "$appprefix\_server.pl");
68ccb5e5 426}
427
428sub _mk_test {
429 my $self = shift;
430 my $script = $self->{script};
431 my $appprefix = $self->{appprefix};
068587bd 432 $self->render_sharedir_file( file('script', 'myapp_test.pl.tt'), file($script, "$appprefix\_test.pl") );
433 chmod 0700, file($script, "$appprefix\_test.pl");
68ccb5e5 434}
435
436sub _mk_create {
437 my $self = shift;
438 my $script = $self->{script};
439 my $appprefix = $self->{appprefix};
068587bd 440 $self->render_sharedir_file( file('script', 'myapp_create.pl.tt'), file($script, "$appprefix\_create.pl") );
441 chmod 0700, file($script, "$appprefix\_create.pl");
68ccb5e5 442}
443
444sub _mk_compclass {
445 my $self = shift;
446 my $file = $self->{file};
068587bd 447 return $self->render_sharedir_file( file('lib', 'Helper', 'compclass.pm.tt'), $file );
68ccb5e5 448}
449
450sub _mk_comptest {
451 my $self = shift;
452 my $test = $self->{test};
068587bd 453 $self->render_sharedir_file( file('t', 'comptest.tt'), $test ); ## wtf do i rename this to?
68ccb5e5 454}
455
456sub _mk_images {
457 my $self = shift;
458 my $images = $self->{images};
459 my @images =
460 qw/catalyst_logo btn_120x50_built btn_120x50_built_shadow
461 btn_120x50_powered btn_120x50_powered_shadow btn_88x31_built
462 btn_88x31_built_shadow btn_88x31_powered btn_88x31_powered_shadow/;
463 for my $name (@images) {
3f2f19ec 464 my $image = $self->get_sharedir_file("root", "static", "images", "$name.png.bin");
068587bd 465 $self->mk_file( file( $images, "$name.png" ), $image );
68ccb5e5 466 }
467}
468
469sub _mk_favicon {
470 my $self = shift;
471 my $root = $self->{root};
f023d4a1 472 my $favicon = $self->get_sharedir_file( 'root', 'favicon.ico.bin' );
068587bd 473 my $dest = dir( $root, "favicon.ico" );
afd739f1 474 $self->mk_file( $dest, $favicon );
68ccb5e5 475
476}
477
478sub _deprecate_file {
479 my ( $self, $file ) = @_;
480 if ( -e $file ) {
28d172c6 481 my ($f, $oldcontent);
482 if ( $f = IO::File->new("< $file") ) {
68ccb5e5 483 $oldcontent = join( '', (<$f>) );
484 }
485 my $newfile = $file . '.deprecated';
28d172c6 486 if ( $f = IO::File->new("> $newfile") ) {
68ccb5e5 487 binmode $f;
488 print $f $oldcontent;
489 print qq/created "$newfile"\n/;
490 unlink $file;
491 print qq/removed "$file"\n/;
492 return 1;
493 }
494 Catalyst::Exception->throw(
495 message => qq/Couldn't create "$file", "$!"/ );
496 }
497}
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
acde1869 582The helpers will read author name from /etc/passwd by default.
583To override, please export the AUTHOR variable.
bc8d7994 584
585=head1 METHODS
586
fab70e0a 587=head2 mk_compclass
588
589This method in your Helper module is called with C<$helper>
590which is a L<Catalyst::Helper> object, and whichever other arguments
591the user added to the command-line. You can use the $helper to call methods
592described below.
593
594If the Helper module does not contain a C<mk_compclass> method, it
595will fall back to calling L</render_file>, with an argument of
596C<compclass>.
597
598=head2 mk_comptest
599
600This method in your Helper module is called with C<$helper>
601which is a L<Catalyst::Helper> object, and whichever other arguments
602the user added to the command-line. You can use the $helper to call methods
603described below.
604
605If the Helper module does not contain a C<mk_compclass> method, it
606will fall back to calling L</render_file>, with an argument of
607C<comptest>.
608
609=head2 mk_stuff
610
611This method is called if the user does not supply any of the usual
612component types C<view>, C<controller>, C<model>. It is passed the
613C<$helper> object (an instance of L<Catalyst::Helper>), and any other
614arguments the user typed.
615
616There is no fallback for this method.
617
bc8d7994 618=head1 INTERNAL METHODS
fab70e0a 619
620These are the methods that the Helper classes can call on the
621<$helper> object passed to them.
622
28eb1300 623=head2 render_file ($file, $path, $vars)
fab70e0a 624
28eb1300 625Render and create a file from a template in DATA using Template
626Toolkit. $file is the relevent chunk of the __DATA__ section, $path is
627the path to the file and $vars is the hashref as expected by
628L<Template Toolkit|Template>.
fab70e0a 629
28eb1300 630=head2 get_file ($class, $file)
fab70e0a 631
632Fetch file contents from the DATA section. This is used internally by
28eb1300 633L</render_file>. $class is the name of the class to get the DATA
634section from. __PACKAGE__ or ( caller(0) )[0] might be sensible
635values for this.
fab70e0a 636
637=head2 mk_app
638
639Create the main application skeleton. This is called by L<catalyst.pl>.
640
28eb1300 641=head2 mk_component ($app)
fab70e0a 642
643This method is called by L<create.pl> to make new components
644for your application.
645
608f6b92 646=head2 mk_dir ($path)
fab70e0a 647
648Surprisingly, this function makes a directory.
649
28eb1300 650=head2 mk_file ($file, $content)
fab70e0a 651
652Writes content to a file. Called by L</render_file>.
653
28eb1300 654=head2 next_test ($test_name)
fab70e0a 655
656Calculates the name of the next numbered test file and returns it.
28eb1300 657Don't give the number or the .t suffix for the test name.
fab70e0a 658
c6dbb300 659=cut
660
661=head2 get_sharedir_file
662
663Method for getting a file out of share/
664
665=cut
666
667=head2 render_file_contents
668
669Process a L<Template::Toolkit> template.
670
671=cut
672
673=head2 render_sharedir_file
674
675Render a template/image file from our share directory
676
677=cut
678
68ccb5e5 679=head1 NOTE
680
681The helpers will read author name from /etc/passwd by default.
682To override, please export the AUTHOR variable.
683
684=head1 SEE ALSO
685
686L<Catalyst::Manual>, L<Catalyst::Test>, L<Catalyst::Request>,
687L<Catalyst::Response>, L<Catalyst>
688
f64c718c 689=head1 AUTHORS
68ccb5e5 690
f64c718c 691Catalyst Contributors, see Catalyst.pm
68ccb5e5 692
693=head1 LICENSE
694
7cd3b67e 695This library is free software. You can redistribute it and/or modify
68ccb5e5 696it under the same terms as Perl itself.
697
698=cut
699
7001;
68ccb5e5 701