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