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