Moved all setup methods to Catalyst::Setup
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
CommitLineData
fc7ec1d9 1package Catalyst;
2
3use strict;
5d9a6d47 4use base qw[ Catalyst::Base Catalyst::Setup ];
fc7ec1d9 5use UNIVERSAL::require;
a2f2cde9 6use Catalyst::Exception;
fc7ec1d9 7use Catalyst::Log;
812a28c9 8use Catalyst::Utils;
5d9a6d47 9use NEXT;
0f7ecc53 10use Text::ASCIITable;
4f6748f1 11use Path::Class;
367d15f8 12our $CATALYST_SCRIPT_GEN = 4;
fc7ec1d9 13
5d9a6d47 14__PACKAGE__->mk_classdata($_) for qw/arguments dispatcher engine log/;
fc7ec1d9 15
abddf0b5 16our $VERSION = '5.24';
fc7ec1d9 17our @ISA;
18
19=head1 NAME
20
21Catalyst - The Elegant MVC Web Application Framework
22
23=head1 SYNOPSIS
24
25 # use the helper to start a new application
91864987 26 catalyst.pl MyApp
fc7ec1d9 27 cd MyApp
28
29 # add models, views, controllers
ae4e40a7 30 script/myapp_create.pl model Something
31 script/myapp_create.pl view Stuff
32 script/myapp_create.pl controller Yada
fc7ec1d9 33
34 # built in testserver
ae4e40a7 35 script/myapp_server.pl
fc7ec1d9 36
37 # command line interface
ae4e40a7 38 script/myapp_test.pl /yada
fc7ec1d9 39
40
fc7ec1d9 41 use Catalyst;
42
43 use Catalyst qw/My::Module My::OtherModule/;
44
45 use Catalyst '-Debug';
46
47 use Catalyst qw/-Debug -Engine=CGI/;
48
5a8ed4fe 49 sub default : Private { $_[1]->res->output('Hello') } );
50
e3dc9d78 51 sub index : Path('/index.html') {
5a8ed4fe 52 my ( $self, $c ) = @_;
53 $c->res->output('Hello');
064834ea 54 $c->forward('foo');
5a8ed4fe 55 }
56
064834ea 57 sub product : Regex('^product[_]*(\d*).html$') {
5a8ed4fe 58 my ( $self, $c ) = @_;
59 $c->stash->{template} = 'product.tt';
60 $c->stash->{product} = $c->req->snippets->[0];
61 }
fc7ec1d9 62
3803e98f 63See also L<Catalyst::Manual::Intro>
64
fc7ec1d9 65=head1 DESCRIPTION
66
fc7ec1d9 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 {
0319a12c 128 my ( $class, @arguments ) = @_;
38cb5be3 129
fc7ec1d9 130 my $caller = caller(0);
38cb5be3 131
132 if ( $caller eq 'main' ) {
133 return;
134 }
fc7ec1d9 135
99fe1710 136 # Prepare inheritance
0319a12c 137 unless ( $caller->isa($class) ) {
fc7ec1d9 138 no strict 'refs';
0319a12c 139 push @{"$caller\::ISA"}, $class;
1c99e125 140 }
38cb5be3 141
d96e14c2 142 if ( $caller->engine ) {
38cb5be3 143 $caller->log->warn( qq/Attempt to re-initialize "$caller"/ );
0319a12c 144 return;
d96e14c2 145 }
146
0319a12c 147 # Process options
148 my $flags = { };
149
150 foreach (@arguments) {
151
152 if ( /^-Debug$/ ) {
c5c6deba 153 $flags->{log} = ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
0319a12c 154 }
155 elsif (/^-(\w+)=?(.*)$/) {
156 $flags->{ lc $1 } = $2;
157 }
158 else {
159 push @{ $flags->{plugins} }, $_;
160 }
161 }
162
163 $caller->setup_log ( delete $flags->{log} );
164 $caller->setup_plugins ( delete $flags->{plugins} );
165 $caller->setup_dispatcher ( delete $flags->{dispatcher} );
166 $caller->setup_engine ( delete $flags->{engine} );
167 $caller->setup_home ( delete $flags->{home} );
168
169 for my $flag ( sort keys %{ $flags } ) {
170
171 if ( my $code = $caller->can( 'setup_' . $flag ) ) {
172 &$code( $caller, delete $flags->{$flag} );
173 }
174 else {
175 $caller->log->warn(qq/Unknown flag "$flag"/);
176 }
177 }
178
179 $caller->log->warn( "You are running an old helper script! "
180 . "Please update your scripts by regenerating the "
181 . "application and copying over the new scripts." )
182 if ( $ENV{CATALYST_SCRIPT_GEN}
183 && ( $ENV{CATALYST_SCRIPT_GEN} < $CATALYST_SCRIPT_GEN ) );
184
185
186 if ( $caller->debug ) {
187
188 my @plugins = ();
189
190 {
191 no strict 'refs';
192 @plugins = grep { /^Catalyst::Plugin/ } @{"$caller\::ISA"};
193 }
194
195 if ( @plugins ) {
196 my $t = Text::ASCIITable->new;
197 $t->setOptions( 'hide_HeadRow', 1 );
198 $t->setOptions( 'hide_HeadLine', 1 );
199 $t->setCols('Class');
200 $t->setColWidth( 'Class', 75, 1 );
201 $t->addRow($_) for @plugins;
f45789b1 202 $caller->log->debug( "Loaded plugins:\n" . $t->draw );
0319a12c 203 }
204
205 my $dispatcher = $caller->dispatcher;
206 my $engine = $caller->engine;
207 my $home = $caller->config->{home};
208
209 $caller->log->debug(qq/Loaded dispatcher "$dispatcher"/);
210 $caller->log->debug(qq/Loaded engine "$engine"/);
211
212 $home
213 ? ( -d $home )
214 ? $caller->log->debug(qq/Found home "$home"/)
215 : $caller->log->debug(qq/Home "$home" doesn't exist/)
216 : $caller->log->debug(q/Couldn't find home/);
fc7ec1d9 217 }
0319a12c 218}
219
220=item $c->engine
221
222Contains the engine class.
fc7ec1d9 223
0319a12c 224=item $c->log
225
226Contains the logging object. Unless it is already set Catalyst sets this up with a
227C<Catalyst::Log> object. To use your own log class:
228
229 $c->log( MyLogger->new );
230 $c->log->info("now logging with my own logger!");
231
232Your log class should implement the methods described in the C<Catalyst::Log>
233man page.
234
235=item $c->plugin( $name, $class, @args )
236
237Instant plugins for Catalyst.
238Classdata accessor/mutator will be created, class loaded and instantiated.
239
240 MyApp->plugin( 'prototype', 'HTML::Prototype' );
241
242 $c->prototype->define_javascript_functions;
243
244=cut
245
246sub plugin {
247 my ( $class, $name, $plugin, @args ) = @_;
248 $plugin->require;
249
250 if ( my $error = $UNIVERSAL::require::ERROR ) {
251 Catalyst::Exception->throw(
252 message => qq/Couldn't load instant plugin "$plugin", "$error"/
253 );
254 }
255
256 eval { $plugin->import };
257 $class->mk_classdata($name);
258 my $obj;
259 eval { $obj = $plugin->new(@args) };
260
261 if ( $@ ) {
262 Catalyst::Exception->throw(
263 message => qq/Couldn't instantiate instant plugin "$plugin", "$@"/
264 );
265 }
266
267 $class->$name($obj);
268 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
269 if $class->debug;
270}
271
5d9a6d47 272=item $class->setup
0319a12c 273
5d9a6d47 274Setup.
895b2303 275
5d9a6d47 276 MyApp->setup;
895b2303 277
0319a12c 278=cut
895b2303 279
5d9a6d47 280sub setup {
281 my $class = shift;
282
283 # Call plugins setup
284 $class->NEXT::setup;
285
286 # Initialize our data structure
287 $class->components( {} );
288
289 $class->setup_components;
290
291 if ( $class->debug ) {
292 my $t = Text::ASCIITable->new;
293 $t->setOptions( 'hide_HeadRow', 1 );
294 $t->setOptions( 'hide_HeadLine', 1 );
295 $t->setCols('Class');
296 $t->setColWidth( 'Class', 75, 1 );
297 $t->addRow($_) for sort keys %{ $class->components };
298 $class->log->debug( "Loaded components:\n" . $t->draw )
299 if ( @{ $t->{tbl_rows} } );
0319a12c 300 }
145074c2 301
5d9a6d47 302 # Add our self to components, since we are also a component
303 $class->components->{$class} = $class;
145074c2 304
5d9a6d47 305 $class->setup_actions;
145074c2 306
5d9a6d47 307 if ( $class->debug ) {
308 my $name = $class->config->{name} || 'Application';
309 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
a2f2cde9 310 }
87232381 311}
145074c2 312
23f9d934 313=back
314
d1a31ac6 315=head1 LIMITATIONS
316
b2b7d352 317mod_perl2 support is considered experimental and may contain bugs.
d1a31ac6 318
3cb1db8c 319=head1 SUPPORT
320
321IRC:
322
323 Join #catalyst on irc.perl.org.
324
325Mailing-Lists:
326
327 http://lists.rawmode.org/mailman/listinfo/catalyst
328 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 329
432d507d 330Web:
331
332 http://catalyst.perl.org
333
fc7ec1d9 334=head1 SEE ALSO
335
61b1e958 336=over 4
337
338=item L<Catalyst::Manual> - The Catalyst Manual
339
340=item L<Catalyst::Engine> - Core Engine
341
342=item L<Catalyst::Log> - The Log Class.
343
344=item L<Catalyst::Request> - The Request Object
345
346=item L<Catalyst::Response> - The Response Object
347
348=item L<Catalyst::Test> - The test suite.
349
350=back
fc7ec1d9 351
352=head1 AUTHOR
353
354Sebastian Riedel, C<sri@oook.de>
355
356=head1 THANK YOU
357
84cf74e7 358Andy Grundman, Andrew Ford, Andrew Ruthven, Autrijus Tang, Christian Hansen,
ce2b098c 359Christopher Hicks, Dan Sully, Danijel Milicevic, David Naughton,
75aeff23 360Gary Ashton Jones, Geoff Richards, Jesse Sheidlower, Jody Belka,
9cee9588 361Johan Lindstrom, Juan Camacho, Leon Brocard, Marcus Ramberg,
362Tatsuhiko Miyagawa and all the others who've helped.
fc7ec1d9 363
364=head1 LICENSE
365
366This library is free software . You can redistribute it and/or modify it under
367the same terms as perl itself.
368
369=cut
370
3711;