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