minor typos in new Mason.pm
[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;
367d15f8 9our $CATALYST_SCRIPT_GEN = 4;
fc7ec1d9 10
424b2705 11__PACKAGE__->mk_classdata($_) for qw/dispatcher engine log/;
fc7ec1d9 12
367d15f8 13our $VERSION = '5.20';
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};
367d15f8 221 my $appdis = $ENV{ uc($caller) . '_DISPATCHER' };
222 $dispatcher = "Catalyst::Dispatcher::$appdis" if $appdis;
424b2705 223
224 $dispatcher->require;
225 die qq/Couldn't load dispatcher "$dispatcher", "$@"/ if $@;
226 {
227 no strict 'refs';
228 push @{"$caller\::ISA"}, $dispatcher;
229 }
230 $caller->dispatcher($dispatcher);
231 $caller->log->debug(qq/Loaded dispatcher "$dispatcher"/) if $caller->debug;
232
e8bf1b2d 233 # Engine
234 $engine = "Catalyst::Engine::$ENV{CATALYST_ENGINE}"
235 if $ENV{CATALYST_ENGINE};
367d15f8 236 my $appeng = $ENV{ uc($caller) . '_ENGINE' };
237 $engine = "Catalyst::Engine::$appeng" if $appeng;
e8bf1b2d 238
239 $engine->require;
240 die qq/Couldn't load engine "$engine", "$@"/ if $@;
241 {
242 no strict 'refs';
243 push @{"$caller\::ISA"}, $engine;
244 }
245 $caller->engine($engine);
246 $caller->log->debug(qq/Loaded engine "$engine"/) if $caller->debug;
4f6748f1 247
248 # Find home
249 my $name = $caller;
250 $name =~ s/\:\:/\//g;
251 my $path = $INC{"$name.pm"};
252 my $home = file($path)->absolute->dir;
253 $name =~ /(\w+)$/;
254 my $append = $1;
255 my $subdir = dir($home)->subdir($append);
256 for ( split '/', $name ) { $home = dir($home)->parent }
257 if ( $home =~ /blib$/ ) { $home = dir($home)->parent }
8f8532e1 258 elsif ( !-f file( $home, 'Makefile.PL' ) ) { $home = $subdir }
4f6748f1 259
260 if ( $caller->debug ) {
261 $home
262 ? ( -d $home )
263 ? $caller->log->debug(qq/Found home "$home"/)
264 : $caller->log->debug(qq/Home "$home" doesn't exist/)
265 : $caller->log->debug(q/Couldn't find home/);
266 }
267 $caller->config->{home} = $home;
268 $caller->config->{root} = dir($home)->subdir('root');
fc7ec1d9 269}
270
70cb38f0 271=item $c->engine
272
273Contains the engine class.
274
145074c2 275=item $c->log
276
277Contains the logging object. Unless it is already set Catalyst sets this up with a
278C<Catalyst::Log> object. To use your own log class:
279
280 $c->log( MyLogger->new );
281 $c->log->info("now logging with my own logger!");
282
283Your log class should implement the methods described in the C<Catalyst::Log>
284man page.
285
87232381 286=item $c->plugin( $name, $class, @args )
287
288Instant plugins for Catalyst.
289Classdata accessor/mutator will be created, class loaded and instantiated.
290
291 MyApp->plugin( 'prototype', 'HTML::Prototype' );
292
293 $c->prototype->define_javascript_functions;
294
295=cut
296
297sub plugin {
298 my ( $class, $name, $plugin, @args ) = @_;
299 $plugin->require;
300 my $error = $UNIVERSAL::require::ERROR;
301 die qq/Couldn't load instant plugin "$plugin", "$error"/ if $error;
302 eval { $plugin->import };
303 $class->mk_classdata($name);
304 my $obj;
305 eval { $obj = $plugin->new(@args) };
306 die qq/Couldn't instantiate instant plugin "$plugin", "$@"/ if $@;
307 $class->$name($obj);
308 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
309 if $class->debug;
310}
145074c2 311
23f9d934 312=back
313
d1a31ac6 314=head1 LIMITATIONS
315
b2b7d352 316mod_perl2 support is considered experimental and may contain bugs.
d1a31ac6 317
3cb1db8c 318=head1 SUPPORT
319
320IRC:
321
322 Join #catalyst on irc.perl.org.
323
324Mailing-Lists:
325
326 http://lists.rawmode.org/mailman/listinfo/catalyst
327 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 328
432d507d 329Web:
330
331 http://catalyst.perl.org
332
fc7ec1d9 333=head1 SEE ALSO
334
61b1e958 335=over 4
336
337=item L<Catalyst::Manual> - The Catalyst Manual
338
339=item L<Catalyst::Engine> - Core Engine
340
341=item L<Catalyst::Log> - The Log Class.
342
343=item L<Catalyst::Request> - The Request Object
344
345=item L<Catalyst::Response> - The Response Object
346
347=item L<Catalyst::Test> - The test suite.
348
349=back
fc7ec1d9 350
351=head1 AUTHOR
352
353Sebastian Riedel, C<sri@oook.de>
354
355=head1 THANK YOU
356
84cf74e7 357Andy Grundman, Andrew Ford, Andrew Ruthven, Autrijus Tang, Christian Hansen,
ce2b098c 358Christopher Hicks, Dan Sully, Danijel Milicevic, David Naughton,
8f8532e1 359Gary Ashton Jones, Jesse Sheidlower, Jody Belka, Johan Lindstrom, Leon Brocard,
4f6748f1 360Marcus Ramberg, Tatsuhiko Miyagawa and all the others who've helped.
fc7ec1d9 361
362=head1 LICENSE
363
364This library is free software . You can redistribute it and/or modify it under
365the same terms as perl itself.
366
367=cut
368
3691;