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