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