Don't warn if caller is main
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
CommitLineData
fc7ec1d9 1package Catalyst;
2
3use strict;
ac733264 4use base 'Catalyst::Base';
fc7ec1d9 5use UNIVERSAL::require;
a2f2cde9 6use Catalyst::Exception;
fc7ec1d9 7use Catalyst::Log;
812a28c9 8use Catalyst::Utils;
0f7ecc53 9use Text::ASCIITable;
4f6748f1 10use Path::Class;
367d15f8 11our $CATALYST_SCRIPT_GEN = 4;
fc7ec1d9 12
424b2705 13__PACKAGE__->mk_classdata($_) for qw/dispatcher engine log/;
fc7ec1d9 14
abddf0b5 15our $VERSION = '5.24';
fc7ec1d9 16our @ISA;
17
18=head1 NAME
19
20Catalyst - The Elegant MVC Web Application Framework
21
22=head1 SYNOPSIS
23
24 # use the helper to start a new application
91864987 25 catalyst.pl MyApp
fc7ec1d9 26 cd MyApp
27
28 # add models, views, controllers
ae4e40a7 29 script/myapp_create.pl model Something
30 script/myapp_create.pl view Stuff
31 script/myapp_create.pl controller Yada
fc7ec1d9 32
33 # built in testserver
ae4e40a7 34 script/myapp_server.pl
fc7ec1d9 35
36 # command line interface
ae4e40a7 37 script/myapp_test.pl /yada
fc7ec1d9 38
39
fc7ec1d9 40 use Catalyst;
41
42 use Catalyst qw/My::Module My::OtherModule/;
43
44 use Catalyst '-Debug';
45
46 use Catalyst qw/-Debug -Engine=CGI/;
47
5a8ed4fe 48 sub default : Private { $_[1]->res->output('Hello') } );
49
e3dc9d78 50 sub index : Path('/index.html') {
5a8ed4fe 51 my ( $self, $c ) = @_;
52 $c->res->output('Hello');
064834ea 53 $c->forward('foo');
5a8ed4fe 54 }
55
064834ea 56 sub product : Regex('^product[_]*(\d*).html$') {
5a8ed4fe 57 my ( $self, $c ) = @_;
58 $c->stash->{template} = 'product.tt';
59 $c->stash->{product} = $c->req->snippets->[0];
60 }
fc7ec1d9 61
3803e98f 62See also L<Catalyst::Manual::Intro>
63
fc7ec1d9 64=head1 DESCRIPTION
65
fc7ec1d9 66The key concept of Catalyst is DRY (Don't Repeat Yourself).
67
68See L<Catalyst::Manual> for more documentation.
69
23f9d934 70Catalyst plugins can be loaded by naming them as arguments to the "use Catalyst" statement.
1985c30b 71Omit the C<Catalyst::Plugin::> prefix from the plugin name,
23f9d934 72so C<Catalyst::Plugin::My::Module> becomes C<My::Module>.
fc7ec1d9 73
74 use Catalyst 'My::Module';
75
23f9d934 76Special flags like -Debug and -Engine can also be specifed as arguments when
77Catalyst is loaded:
fc7ec1d9 78
79 use Catalyst qw/-Debug My::Module/;
80
23f9d934 81The position of plugins and flags in the chain is important, because they are
82loaded in exactly the order that they appear.
fc7ec1d9 83
23f9d934 84The following flags are supported:
85
86=over 4
87
88=item -Debug
89
90enables debug output, i.e.:
fc7ec1d9 91
92 use Catalyst '-Debug';
93
23f9d934 94this is equivalent to:
fc7ec1d9 95
96 use Catalyst;
97 sub debug { 1 }
98
23f9d934 99=item -Engine
fc7ec1d9 100
101Force Catalyst to use a specific engine.
23f9d934 102Omit the C<Catalyst::Engine::> prefix of the engine name, i.e.:
fc7ec1d9 103
104 use Catalyst '-Engine=CGI';
105
23f9d934 106=back
fc7ec1d9 107
23f9d934 108=head1 METHODS
109
110=over 4
111
112=item debug
fc7ec1d9 113
114Overload to enable debug messages.
115
116=cut
117
118sub debug { 0 }
119
23f9d934 120=item config
fc7ec1d9 121
122Returns a hashref containing your applications settings.
123
124=cut
125
fc7ec1d9 126sub import {
0319a12c 127 my ( $class, @arguments ) = @_;
fc7ec1d9 128 my $caller = caller(0);
129
99fe1710 130 # Prepare inheritance
0319a12c 131 unless ( $caller->isa($class) ) {
fc7ec1d9 132 no strict 'refs';
0319a12c 133 push @{"$caller\::ISA"}, $class;
1c99e125 134 }
135
d96e14c2 136 if ( $caller->engine ) {
aa6d2503 137
138 unless ( $caller eq 'main' ) {
139 $caller->log->warn( qq/Attempt to re-initialize "$caller"/ );
140 }
141
0319a12c 142 return;
d96e14c2 143 }
144
0319a12c 145 # Process options
146 my $flags = { };
147
148 foreach (@arguments) {
149
150 if ( /^-Debug$/ ) {
151 $flags->{log} = 1
152 }
153 elsif (/^-(\w+)=?(.*)$/) {
154 $flags->{ lc $1 } = $2;
155 }
156 else {
157 push @{ $flags->{plugins} }, $_;
158 }
159 }
160
161 $caller->setup_log ( delete $flags->{log} );
162 $caller->setup_plugins ( delete $flags->{plugins} );
163 $caller->setup_dispatcher ( delete $flags->{dispatcher} );
164 $caller->setup_engine ( delete $flags->{engine} );
165 $caller->setup_home ( delete $flags->{home} );
166
167 for my $flag ( sort keys %{ $flags } ) {
168
169 if ( my $code = $caller->can( 'setup_' . $flag ) ) {
170 &$code( $caller, delete $flags->{$flag} );
171 }
172 else {
173 $caller->log->warn(qq/Unknown flag "$flag"/);
174 }
175 }
176
177 $caller->log->warn( "You are running an old helper script! "
178 . "Please update your scripts by regenerating the "
179 . "application and copying over the new scripts." )
180 if ( $ENV{CATALYST_SCRIPT_GEN}
181 && ( $ENV{CATALYST_SCRIPT_GEN} < $CATALYST_SCRIPT_GEN ) );
182
183
184 if ( $caller->debug ) {
185
186 my @plugins = ();
187
188 {
189 no strict 'refs';
190 @plugins = grep { /^Catalyst::Plugin/ } @{"$caller\::ISA"};
191 }
192
193 if ( @plugins ) {
194 my $t = Text::ASCIITable->new;
195 $t->setOptions( 'hide_HeadRow', 1 );
196 $t->setOptions( 'hide_HeadLine', 1 );
197 $t->setCols('Class');
198 $t->setColWidth( 'Class', 75, 1 );
199 $t->addRow($_) for @plugins;
200 $caller->log->debug( 'Loaded plugins', $t->draw );
201 }
202
203 my $dispatcher = $caller->dispatcher;
204 my $engine = $caller->engine;
205 my $home = $caller->config->{home};
206
207 $caller->log->debug(qq/Loaded dispatcher "$dispatcher"/);
208 $caller->log->debug(qq/Loaded engine "$engine"/);
209
210 $home
211 ? ( -d $home )
212 ? $caller->log->debug(qq/Found home "$home"/)
213 : $caller->log->debug(qq/Home "$home" doesn't exist/)
214 : $caller->log->debug(q/Couldn't find home/);
fc7ec1d9 215 }
0319a12c 216}
217
218=item $c->engine
219
220Contains the engine class.
fc7ec1d9 221
0319a12c 222=item $c->log
223
224Contains the logging object. Unless it is already set Catalyst sets this up with a
225C<Catalyst::Log> object. To use your own log class:
226
227 $c->log( MyLogger->new );
228 $c->log->info("now logging with my own logger!");
229
230Your log class should implement the methods described in the C<Catalyst::Log>
231man page.
232
233=item $c->plugin( $name, $class, @args )
234
235Instant plugins for Catalyst.
236Classdata accessor/mutator will be created, class loaded and instantiated.
237
238 MyApp->plugin( 'prototype', 'HTML::Prototype' );
239
240 $c->prototype->define_javascript_functions;
241
242=cut
243
244sub plugin {
245 my ( $class, $name, $plugin, @args ) = @_;
246 $plugin->require;
247
248 if ( my $error = $UNIVERSAL::require::ERROR ) {
249 Catalyst::Exception->throw(
250 message => qq/Couldn't load instant plugin "$plugin", "$error"/
251 );
252 }
253
254 eval { $plugin->import };
255 $class->mk_classdata($name);
256 my $obj;
257 eval { $obj = $plugin->new(@args) };
258
259 if ( $@ ) {
260 Catalyst::Exception->throw(
261 message => qq/Couldn't instantiate instant plugin "$plugin", "$@"/
262 );
263 }
264
265 $class->$name($obj);
266 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
267 if $class->debug;
268}
269
270=item $c->setup_dispatcher
271
272=cut
273
274sub setup_dispatcher {
275 my ( $class, $dispatcher ) = @_;
276
277 if ( $dispatcher ) {
278 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
279 }
280
281 if ( $ENV{CATALYST_DISPATCHER} ) {
282 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
283 }
284
285 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
286 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
287 }
288
289 unless ( $dispatcher ) {
290 $dispatcher = 'Catalyst::Dispatcher';
291 }
292
293 $dispatcher->require;
294
295 if ( $@ ) {
296 Catalyst::Exception->throw(
297 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/
298 );
299 }
300
301 {
1985c30b 302 no strict 'refs';
0319a12c 303 push @{"$class\::ISA"}, $dispatcher;
1985c30b 304 }
305
0319a12c 306 $class->dispatcher($dispatcher);
307}
308
309=item $c->setup_engine
310
311=cut
312
313sub setup_engine {
314 my ( $class, $engine ) = @_;
315
316 if ( $engine ) {
317 $engine = 'Catalyst::Engine::' . $engine;
318 }
6dc87a0f 319
0319a12c 320 if ( $ENV{CATALYST_ENGINE} ) {
321 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
322 }
323
324 if ( $ENV{ uc($class) . '_ENGINE' } ) {
325 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
326 }
327
328 if ( ! $engine && $ENV{MOD_PERL} ) {
6dc87a0f 329
316bf0f0 330 my ( $software, $version ) = $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
331
332 $version =~ s/_//g;
333 $version =~ s/(\.[^.]+)\./$1/g;
334
335 if ( $software eq 'mod_perl') {
336
337 if ( $version >= 1.99922 ) {
338
339 $engine = 'Catalyst::Engine::Apache::MP20';
340
341 if ( Apache2::Request->require ) {
566ee5d7 342 $engine = 'Catalyst::Engine::Apache::MP20::Apreq';
316bf0f0 343 }
344 }
345
346 elsif ( $version >= 1.9901 ) {
347
348 $engine = 'Catalyst::Engine::Apache::MP19';
349
350 if ( Apache::Request->require ) {
566ee5d7 351 $engine = 'Catalyst::Engine::Apache::MP19::Apreq';
316bf0f0 352 }
353 }
354
355 elsif ( $version >= 1.24 ) {
356
357 $engine = 'Catalyst::Engine::Apache::MP13';
358
359 if ( Apache::Request->require ) {
566ee5d7 360 $engine = 'Catalyst::Engine::Apache::MP13::Apreq';
316bf0f0 361 }
362 }
d837e1a7 363
316bf0f0 364 else {
a2f2cde9 365 Catalyst::Exception->throw(
366 message => qq/Unsupported mod_perl version: $ENV{MOD_PERL}/
367 );
316bf0f0 368 }
6dc87a0f 369 }
d837e1a7 370
316bf0f0 371 elsif ( $software eq 'Zeus-Perl' ) {
372 $engine = 'Catalyst::Engine::Zeus';
6dc87a0f 373 }
d837e1a7 374
375 else {
a2f2cde9 376 Catalyst::Exception->throw(
377 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/
378 );
d837e1a7 379 }
6dc87a0f 380 }
1985c30b 381
0319a12c 382 unless ( $engine ) {
383 $engine = 'Catalyst::Engine::CGI';
424b2705 384 }
e8bf1b2d 385
386 $engine->require;
0319a12c 387
a2f2cde9 388 if ( $@ ) {
389 Catalyst::Exception->throw(
390 message => qq/Couldn't load engine "$engine", "$@"/
391 );
392 }
d837e1a7 393
e8bf1b2d 394 {
395 no strict 'refs';
0319a12c 396 push @{"$class\::ISA"}, $engine;
e8bf1b2d 397 }
d837e1a7 398
0319a12c 399 $class->engine($engine);
400}
895b2303 401
0319a12c 402=item $c->setup_home
895b2303 403
0319a12c 404=cut
895b2303 405
0319a12c 406sub setup_home {
407 my ( $class, $home ) = @_;
895b2303 408
0319a12c 409 if ( $ENV{CATALYST_HOME} ) {
410 $home = $ENV{CATALYST_HOME};
895b2303 411 }
412
0319a12c 413 if ( $ENV{ uc($class) . '_HOME' } ) {
414 $home = $ENV{ uc($class) . '_HOME' };
415 }
895b2303 416
0319a12c 417 unless ( $home ) {
418 $home = Catalyst::Utils::home($class);
895b2303 419 }
0319a12c 420
421 if ( $home ) {
422 $class->config->{home} = $home;
423 $class->config->{root} = dir($home)->subdir('root');
4f6748f1 424 }
fc7ec1d9 425}
426
0319a12c 427=item $c->setup_log
70cb38f0 428
0319a12c 429=cut
70cb38f0 430
0319a12c 431sub setup_log {
432 my ( $class, $debug ) = @_;
145074c2 433
0319a12c 434 unless ( $class->log ) {
435 $class->log( Catalyst::Log->new );
436 }
145074c2 437
0319a12c 438 if ( $ENV{CATALYST_DEBUG} || $ENV{ uc($class) . '_DEBUG' } || $debug ) {
439 no strict 'refs';
440 *{"$class\::debug"} = sub { 1 };
441 $class->log->debug('Debug messages enabled');
442 }
443}
145074c2 444
0319a12c 445=item $c->setup_plugins
145074c2 446
0319a12c 447=cut
87232381 448
0319a12c 449sub setup_plugins {
450 my ( $class, $plugins ) = @_;
87232381 451
0319a12c 452 for my $plugin ( @$plugins ) {
87232381 453
0319a12c 454 $plugin = "Catalyst::Plugin::$plugin";
87232381 455
0319a12c 456 $plugin->require;
87232381 457
0319a12c 458 if ( $@ ) {
459 Catalyst::Exception->throw(
460 message => qq/Couldn't load plugin "$plugin", "$@"/
461 );
462 }
a2f2cde9 463
0319a12c 464 {
465 no strict 'refs';
466 push @{"$class\::ISA"}, $plugin;
467 }
a2f2cde9 468 }
87232381 469}
145074c2 470
23f9d934 471=back
472
d1a31ac6 473=head1 LIMITATIONS
474
b2b7d352 475mod_perl2 support is considered experimental and may contain bugs.
d1a31ac6 476
3cb1db8c 477=head1 SUPPORT
478
479IRC:
480
481 Join #catalyst on irc.perl.org.
482
483Mailing-Lists:
484
485 http://lists.rawmode.org/mailman/listinfo/catalyst
486 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 487
432d507d 488Web:
489
490 http://catalyst.perl.org
491
fc7ec1d9 492=head1 SEE ALSO
493
61b1e958 494=over 4
495
496=item L<Catalyst::Manual> - The Catalyst Manual
497
498=item L<Catalyst::Engine> - Core Engine
499
500=item L<Catalyst::Log> - The Log Class.
501
502=item L<Catalyst::Request> - The Request Object
503
504=item L<Catalyst::Response> - The Response Object
505
506=item L<Catalyst::Test> - The test suite.
507
508=back
fc7ec1d9 509
510=head1 AUTHOR
511
512Sebastian Riedel, C<sri@oook.de>
513
514=head1 THANK YOU
515
84cf74e7 516Andy Grundman, Andrew Ford, Andrew Ruthven, Autrijus Tang, Christian Hansen,
ce2b098c 517Christopher Hicks, Dan Sully, Danijel Milicevic, David Naughton,
75aeff23 518Gary Ashton Jones, Geoff Richards, Jesse Sheidlower, Jody Belka,
9cee9588 519Johan Lindstrom, Juan Camacho, Leon Brocard, Marcus Ramberg,
520Tatsuhiko Miyagawa and all the others who've helped.
fc7ec1d9 521
522=head1 LICENSE
523
524This library is free software . You can redistribute it and/or modify it under
525the same terms as perl itself.
526
527=cut
528
5291;