Remove BEGIN from C::Log
[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 ) = @_;
38cb5be3 128
fc7ec1d9 129 my $caller = caller(0);
38cb5be3 130
131 if ( $caller eq 'main' ) {
132 return;
133 }
fc7ec1d9 134
99fe1710 135 # Prepare inheritance
0319a12c 136 unless ( $caller->isa($class) ) {
fc7ec1d9 137 no strict 'refs';
0319a12c 138 push @{"$caller\::ISA"}, $class;
1c99e125 139 }
38cb5be3 140
d96e14c2 141 if ( $caller->engine ) {
38cb5be3 142 $caller->log->warn( qq/Attempt to re-initialize "$caller"/ );
0319a12c 143 return;
d96e14c2 144 }
145
0319a12c 146 # Process options
147 my $flags = { };
148
149 foreach (@arguments) {
150
151 if ( /^-Debug$/ ) {
c5c6deba 152 $flags->{log} = ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
0319a12c 153 }
154 elsif (/^-(\w+)=?(.*)$/) {
155 $flags->{ lc $1 } = $2;
156 }
157 else {
158 push @{ $flags->{plugins} }, $_;
159 }
160 }
161
162 $caller->setup_log ( delete $flags->{log} );
163 $caller->setup_plugins ( delete $flags->{plugins} );
164 $caller->setup_dispatcher ( delete $flags->{dispatcher} );
165 $caller->setup_engine ( delete $flags->{engine} );
166 $caller->setup_home ( delete $flags->{home} );
167
168 for my $flag ( sort keys %{ $flags } ) {
169
170 if ( my $code = $caller->can( 'setup_' . $flag ) ) {
171 &$code( $caller, delete $flags->{$flag} );
172 }
173 else {
174 $caller->log->warn(qq/Unknown flag "$flag"/);
175 }
176 }
177
178 $caller->log->warn( "You are running an old helper script! "
179 . "Please update your scripts by regenerating the "
180 . "application and copying over the new scripts." )
181 if ( $ENV{CATALYST_SCRIPT_GEN}
182 && ( $ENV{CATALYST_SCRIPT_GEN} < $CATALYST_SCRIPT_GEN ) );
183
184
185 if ( $caller->debug ) {
186
187 my @plugins = ();
188
189 {
190 no strict 'refs';
191 @plugins = grep { /^Catalyst::Plugin/ } @{"$caller\::ISA"};
192 }
193
194 if ( @plugins ) {
195 my $t = Text::ASCIITable->new;
196 $t->setOptions( 'hide_HeadRow', 1 );
197 $t->setOptions( 'hide_HeadLine', 1 );
198 $t->setCols('Class');
199 $t->setColWidth( 'Class', 75, 1 );
200 $t->addRow($_) for @plugins;
f45789b1 201 $caller->log->debug( "Loaded plugins:\n" . $t->draw );
0319a12c 202 }
203
204 my $dispatcher = $caller->dispatcher;
205 my $engine = $caller->engine;
206 my $home = $caller->config->{home};
207
208 $caller->log->debug(qq/Loaded dispatcher "$dispatcher"/);
209 $caller->log->debug(qq/Loaded engine "$engine"/);
210
211 $home
212 ? ( -d $home )
213 ? $caller->log->debug(qq/Found home "$home"/)
214 : $caller->log->debug(qq/Home "$home" doesn't exist/)
215 : $caller->log->debug(q/Couldn't find home/);
fc7ec1d9 216 }
0319a12c 217}
218
219=item $c->engine
220
221Contains the engine class.
fc7ec1d9 222
0319a12c 223=item $c->log
224
225Contains the logging object. Unless it is already set Catalyst sets this up with a
226C<Catalyst::Log> object. To use your own log class:
227
228 $c->log( MyLogger->new );
229 $c->log->info("now logging with my own logger!");
230
231Your log class should implement the methods described in the C<Catalyst::Log>
232man page.
233
234=item $c->plugin( $name, $class, @args )
235
236Instant plugins for Catalyst.
237Classdata accessor/mutator will be created, class loaded and instantiated.
238
239 MyApp->plugin( 'prototype', 'HTML::Prototype' );
240
241 $c->prototype->define_javascript_functions;
242
243=cut
244
245sub plugin {
246 my ( $class, $name, $plugin, @args ) = @_;
247 $plugin->require;
248
249 if ( my $error = $UNIVERSAL::require::ERROR ) {
250 Catalyst::Exception->throw(
251 message => qq/Couldn't load instant plugin "$plugin", "$error"/
252 );
253 }
254
255 eval { $plugin->import };
256 $class->mk_classdata($name);
257 my $obj;
258 eval { $obj = $plugin->new(@args) };
259
260 if ( $@ ) {
261 Catalyst::Exception->throw(
262 message => qq/Couldn't instantiate instant plugin "$plugin", "$@"/
263 );
264 }
265
266 $class->$name($obj);
267 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
268 if $class->debug;
269}
270
271=item $c->setup_dispatcher
272
273=cut
274
275sub setup_dispatcher {
276 my ( $class, $dispatcher ) = @_;
277
278 if ( $dispatcher ) {
279 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
280 }
281
282 if ( $ENV{CATALYST_DISPATCHER} ) {
283 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{CATALYST_DISPATCHER};
284 }
285
286 if ( $ENV{ uc($class) . '_DISPATCHER' } ) {
287 $dispatcher = 'Catalyst::Dispatcher::' . $ENV{ uc($class) . '_DISPATCHER' };
288 }
289
290 unless ( $dispatcher ) {
291 $dispatcher = 'Catalyst::Dispatcher';
292 }
293
294 $dispatcher->require;
295
296 if ( $@ ) {
297 Catalyst::Exception->throw(
298 message => qq/Couldn't load dispatcher "$dispatcher", "$@"/
299 );
300 }
301
302 {
1985c30b 303 no strict 'refs';
0319a12c 304 push @{"$class\::ISA"}, $dispatcher;
1985c30b 305 }
306
0319a12c 307 $class->dispatcher($dispatcher);
308}
309
310=item $c->setup_engine
311
312=cut
313
314sub setup_engine {
315 my ( $class, $engine ) = @_;
316
317 if ( $engine ) {
318 $engine = 'Catalyst::Engine::' . $engine;
319 }
6dc87a0f 320
0319a12c 321 if ( $ENV{CATALYST_ENGINE} ) {
322 $engine = 'Catalyst::Engine::' . $ENV{CATALYST_ENGINE};
323 }
324
325 if ( $ENV{ uc($class) . '_ENGINE' } ) {
326 $engine = 'Catalyst::Engine::' . $ENV{ uc($class) . '_ENGINE' };
327 }
328
329 if ( ! $engine && $ENV{MOD_PERL} ) {
6dc87a0f 330
316bf0f0 331 my ( $software, $version ) = $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
332
333 $version =~ s/_//g;
334 $version =~ s/(\.[^.]+)\./$1/g;
335
336 if ( $software eq 'mod_perl') {
337
338 if ( $version >= 1.99922 ) {
339
340 $engine = 'Catalyst::Engine::Apache::MP20';
341
342 if ( Apache2::Request->require ) {
566ee5d7 343 $engine = 'Catalyst::Engine::Apache::MP20::Apreq';
316bf0f0 344 }
345 }
346
347 elsif ( $version >= 1.9901 ) {
348
349 $engine = 'Catalyst::Engine::Apache::MP19';
350
351 if ( Apache::Request->require ) {
566ee5d7 352 $engine = 'Catalyst::Engine::Apache::MP19::Apreq';
316bf0f0 353 }
354 }
355
356 elsif ( $version >= 1.24 ) {
357
358 $engine = 'Catalyst::Engine::Apache::MP13';
359
360 if ( Apache::Request->require ) {
566ee5d7 361 $engine = 'Catalyst::Engine::Apache::MP13::Apreq';
316bf0f0 362 }
363 }
d837e1a7 364
316bf0f0 365 else {
a2f2cde9 366 Catalyst::Exception->throw(
367 message => qq/Unsupported mod_perl version: $ENV{MOD_PERL}/
368 );
316bf0f0 369 }
6dc87a0f 370 }
d837e1a7 371
316bf0f0 372 elsif ( $software eq 'Zeus-Perl' ) {
373 $engine = 'Catalyst::Engine::Zeus';
6dc87a0f 374 }
d837e1a7 375
376 else {
a2f2cde9 377 Catalyst::Exception->throw(
378 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/
379 );
d837e1a7 380 }
6dc87a0f 381 }
1985c30b 382
0319a12c 383 unless ( $engine ) {
384 $engine = 'Catalyst::Engine::CGI';
424b2705 385 }
e8bf1b2d 386
387 $engine->require;
0319a12c 388
a2f2cde9 389 if ( $@ ) {
390 Catalyst::Exception->throw(
391 message => qq/Couldn't load engine "$engine", "$@"/
392 );
393 }
d837e1a7 394
e8bf1b2d 395 {
396 no strict 'refs';
0319a12c 397 push @{"$class\::ISA"}, $engine;
e8bf1b2d 398 }
d837e1a7 399
0319a12c 400 $class->engine($engine);
401}
895b2303 402
0319a12c 403=item $c->setup_home
895b2303 404
0319a12c 405=cut
895b2303 406
0319a12c 407sub setup_home {
408 my ( $class, $home ) = @_;
895b2303 409
0319a12c 410 if ( $ENV{CATALYST_HOME} ) {
411 $home = $ENV{CATALYST_HOME};
895b2303 412 }
413
0319a12c 414 if ( $ENV{ uc($class) . '_HOME' } ) {
415 $home = $ENV{ uc($class) . '_HOME' };
416 }
895b2303 417
0319a12c 418 unless ( $home ) {
419 $home = Catalyst::Utils::home($class);
895b2303 420 }
0319a12c 421
422 if ( $home ) {
423 $class->config->{home} = $home;
424 $class->config->{root} = dir($home)->subdir('root');
4f6748f1 425 }
fc7ec1d9 426}
427
0319a12c 428=item $c->setup_log
70cb38f0 429
0319a12c 430=cut
70cb38f0 431
0319a12c 432sub setup_log {
433 my ( $class, $debug ) = @_;
145074c2 434
0319a12c 435 unless ( $class->log ) {
436 $class->log( Catalyst::Log->new );
437 }
145074c2 438
0319a12c 439 if ( $ENV{CATALYST_DEBUG} || $ENV{ uc($class) . '_DEBUG' } || $debug ) {
440 no strict 'refs';
441 *{"$class\::debug"} = sub { 1 };
442 $class->log->debug('Debug messages enabled');
443 }
444}
145074c2 445
0319a12c 446=item $c->setup_plugins
145074c2 447
0319a12c 448=cut
87232381 449
0319a12c 450sub setup_plugins {
451 my ( $class, $plugins ) = @_;
87232381 452
0319a12c 453 for my $plugin ( @$plugins ) {
87232381 454
0319a12c 455 $plugin = "Catalyst::Plugin::$plugin";
87232381 456
0319a12c 457 $plugin->require;
87232381 458
0319a12c 459 if ( $@ ) {
460 Catalyst::Exception->throw(
461 message => qq/Couldn't load plugin "$plugin", "$@"/
462 );
463 }
a2f2cde9 464
0319a12c 465 {
466 no strict 'refs';
467 push @{"$class\::ISA"}, $plugin;
468 }
a2f2cde9 469 }
87232381 470}
145074c2 471
23f9d934 472=back
473
d1a31ac6 474=head1 LIMITATIONS
475
b2b7d352 476mod_perl2 support is considered experimental and may contain bugs.
d1a31ac6 477
3cb1db8c 478=head1 SUPPORT
479
480IRC:
481
482 Join #catalyst on irc.perl.org.
483
484Mailing-Lists:
485
486 http://lists.rawmode.org/mailman/listinfo/catalyst
487 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 488
432d507d 489Web:
490
491 http://catalyst.perl.org
492
fc7ec1d9 493=head1 SEE ALSO
494
61b1e958 495=over 4
496
497=item L<Catalyst::Manual> - The Catalyst Manual
498
499=item L<Catalyst::Engine> - Core Engine
500
501=item L<Catalyst::Log> - The Log Class.
502
503=item L<Catalyst::Request> - The Request Object
504
505=item L<Catalyst::Response> - The Response Object
506
507=item L<Catalyst::Test> - The test suite.
508
509=back
fc7ec1d9 510
511=head1 AUTHOR
512
513Sebastian Riedel, C<sri@oook.de>
514
515=head1 THANK YOU
516
84cf74e7 517Andy Grundman, Andrew Ford, Andrew Ruthven, Autrijus Tang, Christian Hansen,
ce2b098c 518Christopher Hicks, Dan Sully, Danijel Milicevic, David Naughton,
75aeff23 519Gary Ashton Jones, Geoff Richards, Jesse Sheidlower, Jody Belka,
9cee9588 520Johan Lindstrom, Juan Camacho, Leon Brocard, Marcus Ramberg,
521Tatsuhiko Miyagawa and all the others who've helped.
fc7ec1d9 522
523=head1 LICENSE
524
525This library is free software . You can redistribute it and/or modify it under
526the same terms as perl itself.
527
528=cut
529
5301;