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