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