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