Pod fix for Engine::FastCGI.
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
CommitLineData
fc7ec1d9 1package Catalyst;
2
a7caa492 3use Moose;
4extends 'Catalyst::Component';
fbcc39ad 5use bytes;
a2f2cde9 6use Catalyst::Exception;
fc7ec1d9 7use Catalyst::Log;
fbcc39ad 8use Catalyst::Request;
9use Catalyst::Request::Upload;
10use Catalyst::Response;
812a28c9 11use Catalyst::Utils;
31375184 12use Catalyst::Controller;
364d7324 13use Devel::InnerPackage ();
8f62c91a 14use File::stat;
c50f595c 15use Module::Pluggable::Object ();
c50f595c 16use Text::SimpleTable ();
17use Path::Class::Dir ();
18use Path::Class::File ();
fbcc39ad 19use Time::HiRes qw/gettimeofday tv_interval/;
c50f595c 20use URI ();
933ba403 21use URI::http;
22use URI::https;
6a4a7002 23use Scalar::Util qw/weaken blessed/;
5513038d 24use Tree::Simple qw/use_weak_refs/;
25use Tree::Simple::Visitor::FindByUID;
261c571e 26use attributes;
5789a3d8 27use utf8;
c45c5d37 28use Carp qw/croak carp/;
fc7ec1d9 29
f63c03e4 30BEGIN { require 5.008001; }
31
6680c772 32has stack => (is => 'rw', default => sub { [] });
33has stash => (is => 'rw', default => sub { {} });
34has state => (is => 'rw', default => 0);
b6d4ee6e 35has stats => (is => 'rw');
36has action => (is => 'rw');
6680c772 37has counter => (is => 'rw', default => sub { {} });
38has request => (is => 'rw', default => sub { $_[0]->request_class->new({}) }, required => 1, lazy => 1);
39has response => (is => 'rw', default => sub { $_[0]->response_class->new({}) }, required => 1, lazy => 1);
e63bdf38 40has namespace => (is => 'rw');
41
8767c5a3 42sub depth { scalar @{ shift->stack || [] }; }
0fc2d522 43sub comp { shift->component(@_) }
6680c772 44
45sub req {
46 # carp "the use of req() is deprecated in favour of request()";
47 my $self = shift; return $self->request(@_);
48}
49sub res {
50 # carp "the use of res() is deprecated in favour of response()";
51 my $self = shift; return $self->response(@_);
52}
fbcc39ad 53
54# For backwards compatibility
0fc2d522 55sub finalize_output { shift->finalize_body(@_) };
fbcc39ad 56
57# For statistics
58our $COUNT = 1;
59our $START = time;
60our $RECURSION = 1000;
61our $DETACH = "catalyst_detach\n";
2f381252 62our $GO = "catalyst_go\n";
fbcc39ad 63
b6d4ee6e 64#I imagine that very few of these really need to be class variables. if any.
65#maybe we should just make them attributes with a default?
fbcc39ad 66__PACKAGE__->mk_classdata($_)
3cec521a 67 for qw/components arguments dispatcher engine log dispatcher_class
ac5c933b 68 engine_class context_class request_class response_class stats_class
dc5f035e 69 setup_finished/;
cb0354c6 70
3cec521a 71__PACKAGE__->dispatcher_class('Catalyst::Dispatcher');
72__PACKAGE__->engine_class('Catalyst::Engine::CGI');
73__PACKAGE__->request_class('Catalyst::Request');
74__PACKAGE__->response_class('Catalyst::Response');
dc5f035e 75__PACKAGE__->stats_class('Catalyst::Stats');
fbcc39ad 76
6415bb4d 77# Remember to update this in Catalyst::Runtime as well!
78
2f381252 79our $VERSION = '5.7099_03';
189e2a51 80
fbcc39ad 81sub import {
82 my ( $class, @arguments ) = @_;
83
84 # We have to limit $class to Catalyst to avoid pushing Catalyst upon every
85 # callers @ISA.
86 return unless $class eq 'Catalyst';
87
84ff88cf 88 my $caller = caller();
89 return if $caller eq 'main';
90 my $meta = Moose::Meta::Class->initialize($caller);
91 #Moose->import({ into => $caller }); #do we want to do this?
fbcc39ad 92
93 unless ( $caller->isa('Catalyst') ) {
84ff88cf 94 my @superclasses = ($meta->superclasses, $class, 'Catalyst::Controller');
95 $meta->superclasses(@superclasses);
96 }
97 unless( $meta->has_method('meta') ){
98 $meta->add_method(meta => sub { Moose::Meta::Class->initialize("${caller}") } );
fbcc39ad 99 }
100
101 $caller->arguments( [@arguments] );
102 $caller->setup_home;
103}
fc7ec1d9 104
105=head1 NAME
106
107Catalyst - The Elegant MVC Web Application Framework
108
109=head1 SYNOPSIS
110
e7ad3b81 111See the L<Catalyst::Manual> distribution for comprehensive
112documentation and tutorials.
113
86418559 114 # Install Catalyst::Devel for helpers and other development tools
b4b01a8a 115 # use the helper to create a new application
91864987 116 catalyst.pl MyApp
fc7ec1d9 117
118 # add models, views, controllers
2f381252 119 script/myapp_create.pl model MyDatabase DBIC::Schema create=static dbi:SQLite:/path/to/db
cc95842f 120 script/myapp_create.pl view MyTemplate TT
0ef52a96 121 script/myapp_create.pl controller Search
fc7ec1d9 122
e7f1cf73 123 # built in testserver -- use -r to restart automatically on changes
cc95842f 124 # --help to see all available options
ae4e40a7 125 script/myapp_server.pl
fc7ec1d9 126
0ef52a96 127 # command line testing interface
ae4e40a7 128 script/myapp_test.pl /yada
fc7ec1d9 129
b4b01a8a 130 ### in lib/MyApp.pm
0ef52a96 131 use Catalyst qw/-Debug/; # include plugins here as well
ac5c933b 132
85d9fce6 133 ### In lib/MyApp/Controller/Root.pm (autocreated)
0ef52a96 134 sub foo : Global { # called for /foo, /foo/1, /foo/1/2, etc.
ae1e6b59 135 my ( $self, $c, @args ) = @_; # args are qw/1 2/ for /foo/1/2
136 $c->stash->{template} = 'foo.tt'; # set the template
0ef52a96 137 # lookup something from db -- stash vars are passed to TT
ac5c933b 138 $c->stash->{data} =
b4b01a8a 139 $c->model('Database::Foo')->search( { country => $args[0] } );
0ef52a96 140 if ( $c->req->params->{bar} ) { # access GET or POST parameters
141 $c->forward( 'bar' ); # process another action
ac5c933b 142 # do something else after forward returns
0ef52a96 143 }
144 }
ac5c933b 145
ae1e6b59 146 # The foo.tt TT template can use the stash data from the database
0ef52a96 147 [% WHILE (item = data.next) %]
148 [% item.foo %]
149 [% END %]
ac5c933b 150
0ef52a96 151 # called for /bar/of/soap, /bar/of/soap/10, etc.
152 sub bar : Path('/bar/of/soap') { ... }
fc7ec1d9 153
ae1e6b59 154 # called for all actions, from the top-most controller downwards
ac5c933b 155 sub auto : Private {
0ef52a96 156 my ( $self, $c ) = @_;
b4b01a8a 157 if ( !$c->user_exists ) { # Catalyst::Plugin::Authentication
0ef52a96 158 $c->res->redirect( '/login' ); # require login
159 return 0; # abort request and go immediately to end()
160 }
ae1e6b59 161 return 1; # success; carry on to next action
0ef52a96 162 }
ac5c933b 163
ae1e6b59 164 # called after all actions are finished
ac5c933b 165 sub end : Private {
5a8ed4fe 166 my ( $self, $c ) = @_;
0ef52a96 167 if ( scalar @{ $c->error } ) { ... } # handle errors
168 return if $c->res->body; # already have a response
169 $c->forward( 'MyApp::View::TT' ); # render template
5a8ed4fe 170 }
171
0ef52a96 172 ### in MyApp/Controller/Foo.pm
173 # called for /foo/bar
174 sub bar : Local { ... }
ac5c933b 175
5400c668 176 # called for /blargle
177 sub blargle : Global { ... }
ac5c933b 178
5400c668 179 # an index action matches /foo, but not /foo/1, etc.
180 sub index : Private { ... }
ac5c933b 181
0ef52a96 182 ### in MyApp/Controller/Foo/Bar.pm
183 # called for /foo/bar/baz
184 sub baz : Local { ... }
ac5c933b 185
b4b01a8a 186 # first Root auto is called, then Foo auto, then this
0ef52a96 187 sub auto : Private { ... }
ac5c933b 188
0ef52a96 189 # powerful regular expression paths are also possible
190 sub details : Regex('^product/(\w+)/details$') {
5a8ed4fe 191 my ( $self, $c ) = @_;
0ef52a96 192 # extract the (\w+) from the URI
2982e768 193 my $product = $c->req->captures->[0];
5a8ed4fe 194 }
fc7ec1d9 195
0ef52a96 196See L<Catalyst::Manual::Intro> for additional information.
3803e98f 197
fc7ec1d9 198=head1 DESCRIPTION
199
86418559 200Catalyst is a modern framework for making web applications without the
201pain usually associated with this process. This document is a reference
202to the main Catalyst application. If you are a new user, we suggest you
203start with L<Catalyst::Manual::Tutorial> or L<Catalyst::Manual::Intro>.
fc7ec1d9 204
205See L<Catalyst::Manual> for more documentation.
206
ae1e6b59 207Catalyst plugins can be loaded by naming them as arguments to the "use
208Catalyst" statement. Omit the C<Catalyst::Plugin::> prefix from the
209plugin name, i.e., C<Catalyst::Plugin::My::Module> becomes
210C<My::Module>.
fc7ec1d9 211
0ef52a96 212 use Catalyst qw/My::Module/;
fc7ec1d9 213
836e1134 214If your plugin starts with a name other than C<Catalyst::Plugin::>, you can
215fully qualify the name by using a unary plus:
216
217 use Catalyst qw/
218 My::Module
219 +Fully::Qualified::Plugin::Name
220 /;
221
ae1e6b59 222Special flags like C<-Debug> and C<-Engine> can also be specified as
223arguments when Catalyst is loaded:
fc7ec1d9 224
225 use Catalyst qw/-Debug My::Module/;
226
ae1e6b59 227The position of plugins and flags in the chain is important, because
86418559 228they are loaded in the order in which they appear.
fc7ec1d9 229
23f9d934 230The following flags are supported:
231
b5ecfcf0 232=head2 -Debug
23f9d934 233
f8ad6ea5 234Enables debug output. You can also force this setting from the system
86418559 235environment with CATALYST_DEBUG or <MYAPP>_DEBUG. The environment
236settings override the application, with <MYAPP>_DEBUG having the highest
237priority.
fc7ec1d9 238
b5ecfcf0 239=head2 -Engine
fc7ec1d9 240
ae1e6b59 241Forces Catalyst to use a specific engine. Omit the
242C<Catalyst::Engine::> prefix of the engine name, i.e.:
fc7ec1d9 243
0ef52a96 244 use Catalyst qw/-Engine=CGI/;
fc7ec1d9 245
b5ecfcf0 246=head2 -Home
fbcc39ad 247
ae1e6b59 248Forces Catalyst to use a specific home directory, e.g.:
249
86418559 250 use Catalyst qw[-Home=/usr/mst];
fbcc39ad 251
cc95842f 252This can also be done in the shell environment by setting either the
253C<CATALYST_HOME> environment variable or C<MYAPP_HOME>; where C<MYAPP>
254is replaced with the uppercased name of your application, any "::" in
255the name will be replaced with underscores, e.g. MyApp::Web should use
256MYAPP_WEB_HOME. If both variables are set, the MYAPP_HOME one will be used.
257
b5ecfcf0 258=head2 -Log
fbcc39ad 259
0ef52a96 260Specifies log level.
fbcc39ad 261
dc5f035e 262=head2 -Stats
263
264Enables statistics collection and reporting. You can also force this setting
265from the system environment with CATALYST_STATS or <MYAPP>_STATS. The
266environment settings override the application, with <MYAPP>_STATS having the
267highest priority.
268
ac5c933b 269e.g.
dc5f035e 270
271 use Catalyst qw/-Stats=1/
272
23f9d934 273=head1 METHODS
274
f7b672ef 275=head2 INFORMATION ABOUT THE CURRENT REQUEST
0ef52a96 276
b5ecfcf0 277=head2 $c->action
66e28e3f 278
ae1e6b59 279Returns a L<Catalyst::Action> object for the current action, which
280stringifies to the action name. See L<Catalyst::Action>.
0ef52a96 281
b5ecfcf0 282=head2 $c->namespace
0ef52a96 283
86418559 284Returns the namespace of the current action, i.e., the URI prefix
ae1e6b59 285corresponding to the controller of the current action. For example:
286
287 # in Controller::Foo::Bar
288 $c->namespace; # returns 'foo/bar';
0ef52a96 289
b5ecfcf0 290=head2 $c->request
0ef52a96 291
b5ecfcf0 292=head2 $c->req
0ef52a96 293
86418559 294Returns the current L<Catalyst::Request> object, giving access to
295information about the current client request (including parameters,
296cookies, HTTP headers, etc.). See L<Catalyst::Request>.
0ef52a96 297
b4b01a8a 298=head2 REQUEST FLOW HANDLING
0ef52a96 299
b5ecfcf0 300=head2 $c->forward( $action [, \@arguments ] )
0ef52a96 301
b5ecfcf0 302=head2 $c->forward( $class, $method, [, \@arguments ] )
0ef52a96 303
86418559 304Forwards processing to another action, by its private name. If you give a
b4b01a8a 305class name but no method, C<process()> is called. You may also optionally
306pass arguments in an arrayref. The action will receive the arguments in
cc95842f 307C<@_> and C<< $c->req->args >>. Upon returning from the function,
308C<< $c->req->args >> will be restored to the previous values.
0ef52a96 309
3b984c64 310Any data C<return>ed from the action forwarded to, will be returned by the
d759db1e 311call to forward.
3b984c64 312
313 my $foodata = $c->forward('/foo');
0ef52a96 314 $c->forward('index');
e112461a 315 $c->forward(qw/MyApp::Model::DBIC::Foo do_stuff/);
0ef52a96 316 $c->forward('MyApp::View::TT');
317
86418559 318Note that forward implies an C<<eval { }>> around the call (actually
319C<execute> does), thus de-fatalizing all 'dies' within the called
320action. If you want C<die> to propagate you need to do something like:
f3e6a8c0 321
322 $c->forward('foo');
323 die $c->error if $c->error;
324
86418559 325Or make sure to always return true values from your actions and write
326your code like this:
f3e6a8c0 327
328 $c->forward('foo') || return;
329
0ef52a96 330=cut
331
6680c772 332sub forward { my $c = shift; no warnings 'recursion'; $c->dispatcher->forward( $c, @_ ) }
0ef52a96 333
b5ecfcf0 334=head2 $c->detach( $action [, \@arguments ] )
0ef52a96 335
b5ecfcf0 336=head2 $c->detach( $class, $method, [, \@arguments ] )
0ef52a96 337
264bac8c 338=head2 $c->detach()
339
ac5c933b 340The same as C<forward>, but doesn't return to the previous action when
341processing is finished.
0ef52a96 342
264bac8c 343When called with no arguments it escapes the processing chain entirely.
344
0ef52a96 345=cut
346
347sub detach { my $c = shift; $c->dispatcher->detach( $c, @_ ) }
348
2f381252 349=head2 $c->go( $action [, \@arguments ] )
350
351=head2 $c->go( $class, $method, [, \@arguments ] )
352
353Almost the same as C<detach>, but does a full dispatch, instead of just
354calling the new C<$action> / C<$class-E<gt>$method>. This means that C<begin>,
355C<auto> and the method you go to is called, just like a new request.
356
357C<$c-E<gt>stash> is kept unchanged.
358
359=cut
360
361sub go { my $c = shift; $c->dispatcher->go( $c, @_ ) }
362
b4b01a8a 363=head2 $c->response
364
365=head2 $c->res
366
cc95842f 367Returns the current L<Catalyst::Response> object, see there for details.
b4b01a8a 368
369=head2 $c->stash
370
371Returns a hashref to the stash, which may be used to store data and pass
372it between components during a request. You can also set hash keys by
373passing arguments. The stash is automatically sent to the view. The
374stash is cleared at the end of a request; it cannot be used for
86418559 375persistent storage (for this you must use a session; see
376L<Catalyst::Plugin::Session> for a complete system integrated with
377Catalyst).
b4b01a8a 378
379 $c->stash->{foo} = $bar;
380 $c->stash( { moose => 'majestic', qux => 0 } );
381 $c->stash( bar => 1, gorch => 2 ); # equivalent to passing a hashref
ac5c933b 382
b4b01a8a 383 # stash is automatically passed to the view for use in a template
cc95842f 384 $c->forward( 'MyApp::View::TT' );
b4b01a8a 385
386=cut
387
4090e3bb 388around stash => sub {
389 my $orig = shift;
b4b01a8a 390 my $c = shift;
4090e3bb 391 my $stash = $orig->($c);
b4b01a8a 392 if (@_) {
4090e3bb 393 my $new_stash = @_ > 1 ? {@_} : $_[0];
394 croak('stash takes a hash or hashref') unless ref $new_stash;
395 foreach my $key ( keys %$new_stash ) {
396 $stash->{$key} = $new_stash->{$key};
b4b01a8a 397 }
398 }
0fc2d522 399
4090e3bb 400 return $stash;
401};
0fc2d522 402
b4b01a8a 403
b5ecfcf0 404=head2 $c->error
0ef52a96 405
b5ecfcf0 406=head2 $c->error($error, ...)
0ef52a96 407
b5ecfcf0 408=head2 $c->error($arrayref)
0ef52a96 409
83a8fcac 410Returns an arrayref containing error messages. If Catalyst encounters an
411error while processing a request, it stores the error in $c->error. This
e7ad3b81 412method should only be used to store fatal error messages.
0ef52a96 413
414 my @error = @{ $c->error };
415
416Add a new error.
417
418 $c->error('Something bad happened');
419
0ef52a96 420=cut
421
422sub error {
423 my $c = shift;
424 if ( $_[0] ) {
425 my $error = ref $_[0] eq 'ARRAY' ? $_[0] : [@_];
9ce44430 426 croak @$error unless ref $c;
0ef52a96 427 push @{ $c->{error} }, @$error;
428 }
429 elsif ( defined $_[0] ) { $c->{error} = undef }
430 return $c->{error} || [];
431}
432
b4b01a8a 433
434=head2 $c->state
435
436Contains the return value of the last executed action.
437
ca81eb67 438=head2 $c->clear_errors
439
440Clear errors. You probably don't want to clear the errors unless you are
441implementing a custom error screen.
442
443This is equivalent to running
444
445 $c->error(0);
446
447=cut
448
449sub clear_errors {
450 my $c = shift;
451 $c->error(0);
452}
453
2f381252 454# search components given a name and some prefixes
455sub _comp_search_prefixes {
456 my ( $c, $name, @prefixes ) = @_;
457 my $appclass = ref $c || $c;
458 my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::';
0ef52a96 459
2f381252 460 # map the original component name to the sub part that we will search against
461 my %eligible = map { my $n = $_; $n =~ s{^$appclass\::[^:]+::}{}; $_ => $n; }
462 grep { /$filter/ } keys %{ $c->components };
0756fe3b 463
2f381252 464 # undef for a name will return all
465 return keys %eligible if !defined $name;
0756fe3b 466
2f381252 467 my $query = ref $name ? $name : qr/^$name$/i;
468 my @result = grep { $eligible{$_} =~ m{$query} } keys %eligible;
0756fe3b 469
2f381252 470 return map { $c->components->{ $_ } } @result if @result;
0756fe3b 471
2f381252 472 # if we were given a regexp to search against, we're done.
473 return if ref $name;
0756fe3b 474
2f381252 475 # regexp fallback
476 $query = qr/$name/i;
477 @result = map { $c->components->{ $_ } } grep { $eligible{ $_ } =~ m{$query} } keys %eligible;
0756fe3b 478
2f381252 479 # no results? try against full names
480 if( !@result ) {
481 @result = map { $c->components->{ $_ } } grep { m{$query} } keys %eligible;
482 }
0756fe3b 483
2f381252 484 # don't warn if we didn't find any results, it just might not exist
485 if( @result ) {
486 $c->log->warn( qq(Found results for "${name}" using regexp fallback.) );
487 $c->log->warn( 'Relying on the regexp fallback behavior for component resolution is unreliable and unsafe.' );
488 $c->log->warn( 'If you really want to search, pass in a regexp as the argument.' );
489 }
0756fe3b 490
2f381252 491 return @result;
0756fe3b 492}
493
ac5c933b 494# Find possible names for a prefix
3b88a455 495sub _comp_names {
496 my ( $c, @prefixes ) = @_;
3b88a455 497 my $appclass = ref $c || $c;
498
2f381252 499 my $filter = "^${appclass}::(" . join( '|', @prefixes ) . ')::';
3b88a455 500
2f381252 501 my @names = map { s{$filter}{}; $_; } $c->_comp_search_prefixes( undef, @prefixes );
3b88a455 502 return @names;
503}
504
197bd788 505# Filter a component before returning by calling ACCEPT_CONTEXT if available
506sub _filter_component {
507 my ( $c, $comp, @args ) = @_;
2f381252 508
df543cc2 509 if ( Scalar::Util::blessed($c) && eval { $comp->can('ACCEPT_CONTEXT'); } ) {
197bd788 510 return $comp->ACCEPT_CONTEXT( $c, @args );
511 }
2f381252 512
513 return $comp;
197bd788 514}
515
f7b672ef 516=head2 COMPONENT ACCESSORS
0ef52a96 517
b5ecfcf0 518=head2 $c->controller($name)
af3ff00e 519
0ef52a96 520Gets a L<Catalyst::Controller> instance by name.
af3ff00e 521
522 $c->controller('Foo')->do_stuff;
523
86418559 524If the name is omitted, will return the controller for the dispatched
525action.
649fd1fa 526
2f381252 527If you want to search for controllers, pass in a regexp as the argument.
528
529 # find all controllers that start with Foo
530 my @foo_controllers = $c->controller(qr{^Foo});
531
532
af3ff00e 533=cut
534
535sub controller {
197bd788 536 my ( $c, $name, @args ) = @_;
2f381252 537
538 if( $name ) {
539 my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ );
540 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
541 return $c->_filter_component( $result[ 0 ], @args );
542 }
543
197bd788 544 return $c->component( $c->action->class );
af3ff00e 545}
546
b5ecfcf0 547=head2 $c->model($name)
fc7ec1d9 548
0ef52a96 549Gets a L<Catalyst::Model> instance by name.
550
551 $c->model('Foo')->do_stuff;
fc7ec1d9 552
72f87c4b 553Any extra arguments are directly passed to ACCEPT_CONTEXT.
554
ac5c933b 555If the name is omitted, it will look for
2f381252 556 - a model object in $c->stash->{current_model_instance}, then
a3b71f0f 557 - a model name in $c->stash->{current_model}, then
558 - a config setting 'default_model', or
559 - check if there is only one model, and return it if that's the case.
649fd1fa 560
2f381252 561If you want to search for models, pass in a regexp as the argument.
562
563 # find all models that start with Foo
564 my @foo_models = $c->model(qr{^Foo});
565
fc7ec1d9 566=cut
567
0ef52a96 568sub model {
197bd788 569 my ( $c, $name, @args ) = @_;
2f381252 570
571 if( $name ) {
572 my @result = $c->_comp_search_prefixes( $name, qw/Model M/ );
573 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
574 return $c->_filter_component( $result[ 0 ], @args );
575 }
576
a3b71f0f 577 if (ref $c) {
ac5c933b 578 return $c->stash->{current_model_instance}
a3b71f0f 579 if $c->stash->{current_model_instance};
580 return $c->model( $c->stash->{current_model} )
581 if $c->stash->{current_model};
a3b71f0f 582 }
72f87c4b 583 return $c->model( $c->config->{default_model} )
584 if $c->config->{default_model};
3b88a455 585
2f381252 586 my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/Model M/);
3b88a455 587
2f381252 588 if( $rest ) {
589 $c->log->warn( 'Calling $c->model() will return a random model unless you specify one of:' );
590 $c->log->warn( '* $c->config->{default_model} # the name of the default model to use' );
591 $c->log->warn( '* $c->stash->{current_model} # the name of the model to use for this request' );
592 $c->log->warn( '* $c->stash->{current_model_instance} # the instance of the model to use for this request' );
593 $c->log->warn( 'NB: in version 5.80, the "random" behavior will not work at all.' );
594 }
3b88a455 595
2f381252 596 return $c->_filter_component( $comp );
3b88a455 597}
598
b4b01a8a 599
b5ecfcf0 600=head2 $c->view($name)
0ef52a96 601
602Gets a L<Catalyst::View> instance by name.
fc7ec1d9 603
0ef52a96 604 $c->view('Foo')->do_stuff;
fc7ec1d9 605
72f87c4b 606Any extra arguments are directly passed to ACCEPT_CONTEXT.
607
ac5c933b 608If the name is omitted, it will look for
2f381252 609 - a view object in $c->stash->{current_view_instance}, then
a3b71f0f 610 - a view name in $c->stash->{current_view}, then
611 - a config setting 'default_view', or
612 - check if there is only one view, and return it if that's the case.
649fd1fa 613
2f381252 614If you want to search for views, pass in a regexp as the argument.
615
616 # find all views that start with Foo
617 my @foo_views = $c->view(qr{^Foo});
618
fc7ec1d9 619=cut
620
0ef52a96 621sub view {
197bd788 622 my ( $c, $name, @args ) = @_;
2f381252 623
624 if( $name ) {
625 my @result = $c->_comp_search_prefixes( $name, qw/View V/ );
626 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
627 return $c->_filter_component( $result[ 0 ], @args );
628 }
629
a3b71f0f 630 if (ref $c) {
ac5c933b 631 return $c->stash->{current_view_instance}
a3b71f0f 632 if $c->stash->{current_view_instance};
633 return $c->view( $c->stash->{current_view} )
634 if $c->stash->{current_view};
a3b71f0f 635 }
72f87c4b 636 return $c->view( $c->config->{default_view} )
637 if $c->config->{default_view};
2f381252 638
639 my( $comp, $rest ) = $c->_comp_search_prefixes( undef, qw/View V/);
640
641 if( $rest ) {
642 $c->log->warn( 'Calling $c->view() will return a random view unless you specify one of:' );
643 $c->log->warn( '* $c->config->{default_view} # the name of the default view to use' );
644 $c->log->warn( '* $c->stash->{current_view} # the name of the view to use for this request' );
645 $c->log->warn( '* $c->stash->{current_view_instance} # the instance of the view to use for this request' );
646 $c->log->warn( 'NB: in version 5.80, the "random" behavior will not work at all.' );
647 }
648
649 return $c->_filter_component( $comp );
650}
651
652=head2 $c->controllers
653
654Returns the available names which can be passed to $c->controller
655
656=cut
657
658sub controllers {
659 my ( $c ) = @_;
660 return $c->_comp_names(qw/Controller C/);
0ef52a96 661}
fbcc39ad 662
b4b01a8a 663=head2 $c->models
664
665Returns the available names which can be passed to $c->model
666
667=cut
668
669sub models {
670 my ( $c ) = @_;
671 return $c->_comp_names(qw/Model M/);
672}
673
674
3b88a455 675=head2 $c->views
676
677Returns the available names which can be passed to $c->view
678
679=cut
680
681sub views {
682 my ( $c ) = @_;
683 return $c->_comp_names(qw/View V/);
684}
685
b4b01a8a 686=head2 $c->comp($name)
687
688=head2 $c->component($name)
689
cc95842f 690Gets a component object by name. This method is not recommended,
b4b01a8a 691unless you want to get a specific component by full
cc95842f 692class. C<< $c->controller >>, C<< $c->model >>, and C<< $c->view >>
b4b01a8a 693should be used instead.
694
2f381252 695If C<$name> is a regexp, a list of components matched against the full
696component name will be returned.
697
b4b01a8a 698=cut
699
700sub component {
2f381252 701 my ( $c, $name, @args ) = @_;
b4b01a8a 702
2f381252 703 if( $name ) {
704 my $comps = $c->components;
b4b01a8a 705
2f381252 706 if( !ref $name ) {
707 # is it the exact name?
708 return $c->_filter_component( $comps->{ $name }, @args )
709 if exists $comps->{ $name };
b4b01a8a 710
2f381252 711 # perhaps we just omitted "MyApp"?
712 my $composed = ( ref $c || $c ) . "::${name}";
713 return $c->_filter_component( $comps->{ $composed }, @args )
714 if exists $comps->{ $composed };
b4b01a8a 715
2f381252 716 # search all of the models, views and controllers
717 my( $comp ) = $c->_comp_search_prefixes( $name, qw/Model M Controller C View V/ );
718 return $c->_filter_component( $comp, @args ) if $comp;
719 }
720
721 # This is here so $c->comp( '::M::' ) works
722 my $query = ref $name ? $name : qr{$name}i;
b4b01a8a 723
2f381252 724 my @result = grep { m{$query} } keys %{ $c->components };
725 return map { $c->_filter_component( $_, @args ) } @result if ref $name;
b4b01a8a 726
2f381252 727 if( $result[ 0 ] ) {
728 $c->log->warn( qq(Found results for "${name}" using regexp fallback.) );
729 $c->log->warn( 'Relying on the regexp fallback behavior for component resolution' );
730 $c->log->warn( 'is unreliable and unsafe. You have been warned' );
731 return $c->_filter_component( $result[ 0 ], @args );
732 }
733
734 # I would expect to return an empty list here, but that breaks back-compat
b4b01a8a 735 }
736
2f381252 737 # fallback
b4b01a8a 738 return sort keys %{ $c->components };
739}
740
b4b01a8a 741=head2 CLASS DATA AND HELPER CLASSES
fbcc39ad 742
b5ecfcf0 743=head2 $c->config
fbcc39ad 744
0ef52a96 745Returns or takes a hashref containing the application's configuration.
746
61b1d329 747 __PACKAGE__->config( { db => 'dsn:SQLite:foo.db' } );
81557adf 748
cc95842f 749You can also use a C<YAML>, C<XML> or C<Config::General> config file
750like myapp.yml in your applications home directory. See
751L<Catalyst::Plugin::ConfigLoader>.
a6ad13b6 752
753 ---
754 db: dsn:SQLite:foo.db
755
b4b01a8a 756
3643e890 757=cut
758
4090e3bb 759around config => sub {
760 my $orig = shift;
3643e890 761 my $c = shift;
762
763 $c->log->warn("Setting config after setup has been run is not a good idea.")
764 if ( @_ and $c->setup_finished );
765
4090e3bb 766 $c->$orig(@_);
767};
3643e890 768
b5ecfcf0 769=head2 $c->log
0ef52a96 770
86418559 771Returns the logging object instance. Unless it is already set, Catalyst
772sets this up with a L<Catalyst::Log> object. To use your own log class,
773set the logger with the C<< __PACKAGE__->log >> method prior to calling
9e7673af 774C<< __PACKAGE__->setup >>.
775
776 __PACKAGE__->log( MyLogger->new );
777 __PACKAGE__->setup;
778
779And later:
0ef52a96 780
ae1e6b59 781 $c->log->info( 'Now logging with my own logger!' );
0ef52a96 782
86418559 783Your log class should implement the methods described in
784L<Catalyst::Log>.
af3ff00e 785
b4b01a8a 786
787=head2 $c->debug
788
789Overload to enable debug messages (same as -Debug option).
790
e80e8542 791Note that this is a static method, not an accessor and should be overloaded
792by declaring "sub debug { 1 }" in your MyApp.pm, not by calling $c->debug(1).
793
af3ff00e 794=cut
795
b4b01a8a 796sub debug { 0 }
797
798=head2 $c->dispatcher
799
800Returns the dispatcher instance. Stringifies to class name. See
801L<Catalyst::Dispatcher>.
802
803=head2 $c->engine
804
805Returns the engine instance. Stringifies to the class name. See
806L<Catalyst::Engine>.
807
808
f7b672ef 809=head2 UTILITY METHODS
66e28e3f 810
b5ecfcf0 811=head2 $c->path_to(@path)
01033d73 812
cc95842f 813Merges C<@path> with C<< $c->config->{home} >> and returns a
afbb9aa3 814L<Path::Class::Dir> object.
01033d73 815
816For example:
817
818 $c->path_to( 'db', 'sqlite.db' );
819
820=cut
821
822sub path_to {
823 my ( $c, @path ) = @_;
a738ab68 824 my $path = Path::Class::Dir->new( $c->config->{home}, @path );
01033d73 825 if ( -d $path ) { return $path }
a738ab68 826 else { return Path::Class::File->new( $c->config->{home}, @path ) }
01033d73 827}
828
b5ecfcf0 829=head2 $c->plugin( $name, $class, @args )
0ef52a96 830
ae1e6b59 831Helper method for plugins. It creates a classdata accessor/mutator and
832loads and instantiates the given class.
0ef52a96 833
834 MyApp->plugin( 'prototype', 'HTML::Prototype' );
835
836 $c->prototype->define_javascript_functions;
837
838=cut
839
840sub plugin {
841 my ( $class, $name, $plugin, @args ) = @_;
97b58e17 842 $class->_register_plugin( $plugin, 1 );
0ef52a96 843
844 eval { $plugin->import };
845 $class->mk_classdata($name);
846 my $obj;
847 eval { $obj = $plugin->new(@args) };
848
849 if ($@) {
850 Catalyst::Exception->throw( message =>
851 qq/Couldn't instantiate instant plugin "$plugin", "$@"/ );
852 }
853
854 $class->$name($obj);
855 $class->log->debug(qq/Initialized instant plugin "$plugin" as "$name"/)
856 if $class->debug;
857}
858
b5ecfcf0 859=head2 MyApp->setup
fbcc39ad 860
e7f1cf73 861Initializes the dispatcher and engine, loads any plugins, and loads the
ae1e6b59 862model, view, and controller components. You may also specify an array
863of plugins to load here, if you choose to not load them in the C<use
864Catalyst> line.
fbcc39ad 865
0ef52a96 866 MyApp->setup;
867 MyApp->setup( qw/-Debug/ );
fbcc39ad 868
869=cut
870
871sub setup {
0319a12c 872 my ( $class, @arguments ) = @_;
5168a5fc 873 $class->log->warn("Running setup twice is not a good idea.")
874 if ( $class->setup_finished );
875
fbcc39ad 876 unless ( $class->isa('Catalyst') ) {
953b0e15 877
fbcc39ad 878 Catalyst::Exception->throw(
879 message => qq/'$class' does not inherit from Catalyst/ );
1c99e125 880 }
0319a12c 881
fbcc39ad 882 if ( $class->arguments ) {
883 @arguments = ( @arguments, @{ $class->arguments } );
884 }
885
886 # Process options
887 my $flags = {};
888
889 foreach (@arguments) {
890
891 if (/^-Debug$/) {
892 $flags->{log} =
893 ( $flags->{log} ) ? 'debug,' . $flags->{log} : 'debug';
894 }
895 elsif (/^-(\w+)=?(.*)$/) {
896 $flags->{ lc $1 } = $2;
897 }
898 else {
899 push @{ $flags->{plugins} }, $_;
900 }
901 }
902
99f187d6 903 $class->setup_home( delete $flags->{home} );
904
fbcc39ad 905 $class->setup_log( delete $flags->{log} );
906 $class->setup_plugins( delete $flags->{plugins} );
907 $class->setup_dispatcher( delete $flags->{dispatcher} );
908 $class->setup_engine( delete $flags->{engine} );
dc5f035e 909 $class->setup_stats( delete $flags->{stats} );
fbcc39ad 910
911 for my $flag ( sort keys %{$flags} ) {
912
913 if ( my $code = $class->can( 'setup_' . $flag ) ) {
914 &$code( $class, delete $flags->{$flag} );
915 }
916 else {
917 $class->log->warn(qq/Unknown flag "$flag"/);
918 }
919 }
920
0eb4af72 921 eval { require Catalyst::Devel; };
922 if( !$@ && $ENV{CATALYST_SCRIPT_GEN} && ( $ENV{CATALYST_SCRIPT_GEN} < $Catalyst::Devel::CATALYST_SCRIPT_GEN ) ) {
923 $class->log->warn(<<"EOF");
4ff0d824 924You are running an old script!
925
34a83d89 926 Please update by running (this will overwrite existing files):
927 catalyst.pl -force -scripts $class
928
929 or (this will not overwrite existing files):
930 catalyst.pl -scripts $class
1cf0345b 931
4ff0d824 932EOF
0eb4af72 933 }
ac5c933b 934
fbcc39ad 935 if ( $class->debug ) {
6601f2ad 936 my @plugins = map { "$_ " . ( $_->VERSION || '' ) } $class->registered_plugins;
fbcc39ad 937
938 if (@plugins) {
34d28dfd 939 my $t = Text::SimpleTable->new(74);
8c113188 940 $t->row($_) for @plugins;
1cf0345b 941 $class->log->debug( "Loaded plugins:\n" . $t->draw . "\n" );
fbcc39ad 942 }
943
944 my $dispatcher = $class->dispatcher;
945 my $engine = $class->engine;
946 my $home = $class->config->{home};
947
948 $class->log->debug(qq/Loaded dispatcher "$dispatcher"/);
949 $class->log->debug(qq/Loaded engine "$engine"/);
950
951 $home
952 ? ( -d $home )
953 ? $class->log->debug(qq/Found home "$home"/)
954 : $class->log->debug(qq/Home "$home" doesn't exist/)
955 : $class->log->debug(q/Couldn't find home/);
956 }
957
958 # Call plugins setup
959 {
960 no warnings qw/redefine/;
961 local *setup = sub { };
962 $class->setup;
963 }
964
965 # Initialize our data structure
966 $class->components( {} );
967
968 $class->setup_components;
969
970 if ( $class->debug ) {
34d28dfd 971 my $t = Text::SimpleTable->new( [ 63, 'Class' ], [ 8, 'Type' ] );
684d10ed 972 for my $comp ( sort keys %{ $class->components } ) {
973 my $type = ref $class->components->{$comp} ? 'instance' : 'class';
974 $t->row( $comp, $type );
975 }
1cf0345b 976 $class->log->debug( "Loaded components:\n" . $t->draw . "\n" )
8c113188 977 if ( keys %{ $class->components } );
fbcc39ad 978 }
979
980 # Add our self to components, since we are also a component
96d8d513 981 if( $class->isa('Catalyst::Controller') ){
982 $class->components->{$class} = $class;
983 }
fbcc39ad 984
985 $class->setup_actions;
986
987 if ( $class->debug ) {
988 my $name = $class->config->{name} || 'Application';
989 $class->log->info("$name powered by Catalyst $Catalyst::VERSION");
990 }
991 $class->log->_flush() if $class->log->can('_flush');
3643e890 992
993 $class->setup_finished(1);
fbcc39ad 994}
995
73664287 996=head2 $c->uri_for( $path, @args?, \%query_values? )
fbcc39ad 997
c50f595c 998Merges path with C<< $c->request->base >> for absolute URIs and with
999C<< $c->namespace >> for relative URIs, then returns a normalized L<URI>
86418559 1000object. If any args are passed, they are added at the end of the path.
1001If the last argument to C<uri_for> is a hash reference, it is assumed to
1002contain GET parameter key/value pairs, which will be appended to the URI
1003in standard fashion.
fbcc39ad 1004
8dc69021 1005Note that uri_for is destructive to the passed hashref. Subsequent calls
1006with the same hashref may have unintended results.
1007
86418559 1008Instead of C<$path>, you can also optionally pass a C<$action> object
1009which will be resolved to a path using
147869cd 1010C<< $c->dispatcher->uri_for_action >>; if the first element of
86418559 1011C<@args> is an arrayref it is treated as a list of captures to be passed
1012to C<uri_for_action>.
ea0e58d9 1013
9df7c5d9 1014You can maintain the arguments captured by an action (e.g.: Regex, Chained)
1015using C<< $c->req->captures >>.
1016
1017 # For the current action
1018 $c->uri_for($c->action, $c->req->captures);
1019
1020 # For the Foo action in the Bar controller
1021 $c->uri_for($c->controller->('Bar')->action_for('Foo'), $c->req->captures);
1022
fbcc39ad 1023=cut
1024
1025sub uri_for {
00e6a2b7 1026 my ( $c, $path, @args ) = @_;
00e6a2b7 1027
ea0e58d9 1028 if ( Scalar::Util::blessed($path) ) { # action object
1029 my $captures = ( scalar @args && ref $args[0] eq 'ARRAY'
1030 ? shift(@args)
1031 : [] );
1032 $path = $c->dispatcher->uri_for_action($path, $captures);
1033 return undef unless defined($path);
81e75875 1034 $path = '/' if $path eq '';
ea0e58d9 1035 }
1036
51674a63 1037 undef($path) if (defined $path && $path eq '');
00e6a2b7 1038
97b58e17 1039 my $params =
1040 ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} );
8327e2e2 1041
cbb93105 1042 carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
51674a63 1043 s/([^$URI::uric])/$URI::Escape::escapes{$1}/go for @args;
1044
1045 unshift(@args, $path);
1046
1047 unless (defined $path && $path =~ s!^/!!) { # in-place strip
1048 my $namespace = $c->namespace;
1049 if (defined $path) { # cheesy hack to handle path '../foo'
1050 $namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{};
6601f2ad 1051 }
51674a63 1052 unshift(@args, $namespace || '');
1053 }
ac5c933b 1054
189e2a51 1055 # join args with '/', or a blank string
51674a63 1056 my $args = join('/', grep { defined($_) } @args);
1057 $args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
1058 $args =~ s!^/!!;
1059 my $base = $c->req->base;
1060 my $class = ref($base);
1061 $base =~ s{(?<!/)$}{/};
1062
1063 my $query = '';
1064
1065 if (my @keys = keys %$params) {
1066 # somewhat lifted from URI::_query's query_form
1067 $query = '?'.join('&', map {
2f381252 1068 my $val = $params->{$_};
51674a63 1069 s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go;
1070 s/ /+/g;
1071 my $key = $_;
51674a63 1072 $val = '' unless defined $val;
1073 (map {
1074 $_ = "$_";
0ce485e9 1075 utf8::encode( $_ ) if utf8::is_utf8($_);
51674a63 1076 # using the URI::Escape pattern here so utf8 chars survive
1077 s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
1078 s/ /+/g;
1079 "${key}=$_"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
1080 } @keys);
1081 }
1082
1083 my $res = bless(\"${base}${args}${query}", $class);
d3e7a648 1084 $res;
fbcc39ad 1085}
1086
b5ecfcf0 1087=head2 $c->welcome_message
ab2374d3 1088
1089Returns the Catalyst welcome HTML page.
1090
1091=cut
1092
1093sub welcome_message {
bf1f2c60 1094 my $c = shift;
1095 my $name = $c->config->{name};
1096 my $logo = $c->uri_for('/static/images/catalyst_logo.png');
1097 my $prefix = Catalyst::Utils::appprefix( ref $c );
80cdbbff 1098 $c->response->content_type('text/html; charset=utf-8');
ab2374d3 1099 return <<"EOF";
80cdbbff 1100<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1101 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
1102<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
ab2374d3 1103 <head>
85d9fce6 1104 <meta http-equiv="Content-Language" content="en" />
1105 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
ab2374d3 1106 <title>$name on Catalyst $VERSION</title>
1107 <style type="text/css">
1108 body {
ab2374d3 1109 color: #000;
1110 background-color: #eee;
1111 }
1112 div#content {
1113 width: 640px;
80cdbbff 1114 margin-left: auto;
1115 margin-right: auto;
ab2374d3 1116 margin-top: 10px;
1117 margin-bottom: 10px;
1118 text-align: left;
1119 background-color: #ccc;
1120 border: 1px solid #aaa;
ab2374d3 1121 }
d84c4dab 1122 p, h1, h2 {
ab2374d3 1123 margin-left: 20px;
1124 margin-right: 20px;
16215972 1125 font-family: verdana, tahoma, sans-serif;
ab2374d3 1126 }
d84c4dab 1127 a {
1128 font-family: verdana, tahoma, sans-serif;
1129 }
d114e033 1130 :link, :visited {
1131 text-decoration: none;
1132 color: #b00;
1133 border-bottom: 1px dotted #bbb;
1134 }
1135 :link:hover, :visited:hover {
d114e033 1136 color: #555;
1137 }
ab2374d3 1138 div#topbar {
1139 margin: 0px;
1140 }
3e82a295 1141 pre {
3e82a295 1142 margin: 10px;
1143 padding: 8px;
1144 }
ab2374d3 1145 div#answers {
1146 padding: 8px;
1147 margin: 10px;
d114e033 1148 background-color: #fff;
ab2374d3 1149 border: 1px solid #aaa;
ab2374d3 1150 }
1151 h1 {
33108eaf 1152 font-size: 0.9em;
1153 font-weight: normal;
ab2374d3 1154 text-align: center;
1155 }
1156 h2 {
1157 font-size: 1.0em;
1158 }
1159 p {
1160 font-size: 0.9em;
1161 }
ae7c5252 1162 p img {
1163 float: right;
1164 margin-left: 10px;
1165 }
9619f23c 1166 span#appname {
1167 font-weight: bold;
33108eaf 1168 font-size: 1.6em;
ab2374d3 1169 }
1170 </style>
1171 </head>
1172 <body>
1173 <div id="content">
1174 <div id="topbar">
9619f23c 1175 <h1><span id="appname">$name</span> on <a href="http://catalyst.perl.org">Catalyst</a>
d84c4dab 1176 $VERSION</h1>
ab2374d3 1177 </div>
1178 <div id="answers">
ae7c5252 1179 <p>
80cdbbff 1180 <img src="$logo" alt="Catalyst Logo" />
ae7c5252 1181 </p>
596aaffe 1182 <p>Welcome to the world of Catalyst.
f92fd545 1183 This <a href="http://en.wikipedia.org/wiki/MVC">MVC</a>
1184 framework will make web development something you had
60dd6e1d 1185 never expected it to be: Fun, rewarding, and quick.</p>
ab2374d3 1186 <h2>What to do now?</h2>
4b8cb778 1187 <p>That really depends on what <b>you</b> want to do.
ab2374d3 1188 We do, however, provide you with a few starting points.</p>
1189 <p>If you want to jump right into web development with Catalyst
2f381252 1190 you might want to start with a tutorial.</p>
b607f8a0 1191<pre>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Tutorial.pod">Catalyst::Manual::Tutorial</a></code>
596aaffe 1192</pre>
1193<p>Afterwards you can go on to check out a more complete look at our features.</p>
1194<pre>
b607f8a0 1195<code>perldoc <a href="http://cpansearch.perl.org/dist/Catalyst-Manual/lib/Catalyst/Manual/Intro.pod">Catalyst::Manual::Intro</a>
1196<!-- Something else should go here, but the Catalyst::Manual link seems unhelpful -->
1197</code></pre>
ab2374d3 1198 <h2>What to do next?</h2>
f5681c92 1199 <p>Next it's time to write an actual application. Use the
80cdbbff 1200 helper scripts to generate <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AController%3A%3A&amp;mode=all">controllers</a>,
60dd6e1d 1201 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AModel%3A%3A&amp;mode=all">models</a>, and
1202 <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3AView%3A%3A&amp;mode=all">views</a>;
bf1f2c60 1203 they can save you a lot of work.</p>
1204 <pre><code>script/${prefix}_create.pl -help</code></pre>
1205 <p>Also, be sure to check out the vast and growing
60dd6e1d 1206 collection of <a href="http://cpansearch.perl.org/search?query=Catalyst%3A%3APlugin%3A%3A&amp;mode=all">plugins for Catalyst on CPAN</a>;
bf1f2c60 1207 you are likely to find what you need there.
f5681c92 1208 </p>
1209
82245cc4 1210 <h2>Need help?</h2>
f5681c92 1211 <p>Catalyst has a very active community. Here are the main places to
1212 get in touch with us.</p>
16215972 1213 <ul>
1214 <li>
2b9a7d76 1215 <a href="http://dev.catalyst.perl.org">Wiki</a>
16215972 1216 </li>
1217 <li>
1218 <a href="http://lists.rawmode.org/mailman/listinfo/catalyst">Mailing-List</a>
1219 </li>
1220 <li>
4eaf7c88 1221 <a href="irc://irc.perl.org/catalyst">IRC channel #catalyst on irc.perl.org</a>
16215972 1222 </li>
1223 </ul>
ab2374d3 1224 <h2>In conclusion</h2>
ac5c933b 1225 <p>The Catalyst team hopes you will enjoy using Catalyst as much
f5681c92 1226 as we enjoyed making it. Please contact us if you have ideas
1227 for improvement or other feedback.</p>
ab2374d3 1228 </div>
1229 </div>
1230 </body>
1231</html>
1232EOF
1233}
1234
fbcc39ad 1235=head1 INTERNAL METHODS
1236
ae1e6b59 1237These methods are not meant to be used by end users.
1238
b5ecfcf0 1239=head2 $c->components
fbcc39ad 1240
e7f1cf73 1241Returns a hash of components.
fbcc39ad 1242
b5ecfcf0 1243=head2 $c->context_class
1f9cb7c1 1244
e7f1cf73 1245Returns or sets the context class.
1f9cb7c1 1246
b5ecfcf0 1247=head2 $c->counter
fbcc39ad 1248
ae1e6b59 1249Returns a hashref containing coderefs and execution counts (needed for
1250deep recursion detection).
fbcc39ad 1251
b5ecfcf0 1252=head2 $c->depth
fbcc39ad 1253
e7f1cf73 1254Returns the number of actions on the current internal execution stack.
fbcc39ad 1255
b5ecfcf0 1256=head2 $c->dispatch
fbcc39ad 1257
e7f1cf73 1258Dispatches a request to actions.
fbcc39ad 1259
1260=cut
1261
1262sub dispatch { my $c = shift; $c->dispatcher->dispatch( $c, @_ ) }
1263
b5ecfcf0 1264=head2 $c->dispatcher_class
1f9cb7c1 1265
e7f1cf73 1266Returns or sets the dispatcher class.
1f9cb7c1 1267
b5ecfcf0 1268=head2 $c->dump_these
7f92deef 1269
ae1e6b59 1270Returns a list of 2-element array references (name, structure) pairs
1271that will be dumped on the error page in debug mode.
7f92deef 1272
1273=cut
1274
1275sub dump_these {
1276 my $c = shift;
ac5c933b 1277 [ Request => $c->req ],
1278 [ Response => $c->res ],
052a2d89 1279 [ Stash => $c->stash ],
1280 [ Config => $c->config ];
7f92deef 1281}
1282
b5ecfcf0 1283=head2 $c->engine_class
1f9cb7c1 1284
e7f1cf73 1285Returns or sets the engine class.
1f9cb7c1 1286
b5ecfcf0 1287=head2 $c->execute( $class, $coderef )
fbcc39ad 1288
0ef52a96 1289Execute a coderef in given class and catch exceptions. Errors are available
1290via $c->error.
fbcc39ad 1291
1292=cut
1293
1294sub execute {
1295 my ( $c, $class, $code ) = @_;
858828dd 1296 $class = $c->component($class) || $class;
fbcc39ad 1297 $c->state(0);
a0eca838 1298
197bd788 1299 if ( $c->depth >= $RECURSION ) {
f3414019 1300 my $action = $code->reverse();
91d08727 1301 $action = "/$action" unless $action =~ /->/;
f3414019 1302 my $error = qq/Deep recursion detected calling "${action}"/;
1627551a 1303 $c->log->error($error);
1304 $c->error($error);
1305 $c->state(0);
1306 return $c->state;
1307 }
1308
dc5f035e 1309 my $stats_info = $c->_stats_start_execute( $code ) if $c->use_stats;
22247e54 1310
8767c5a3 1311 push( @{ $c->stack }, $code );
ac5c933b 1312
f3414019 1313 eval { $c->state( $code->execute( $class, $c, @{ $c->req->args } ) || 0 ) };
22247e54 1314
dc5f035e 1315 $c->_stats_finish_execute( $stats_info ) if $c->use_stats and $stats_info;
ac5c933b 1316
a6724a82 1317 my $last = pop( @{ $c->stack } );
fbcc39ad 1318
1319 if ( my $error = $@ ) {
2f381252 1320 if ( !ref($error) and $error eq $DETACH ) {
1321 die $DETACH if($c->depth > 1);
1322 }
1323 elsif ( !ref($error) and $error eq $GO ) {
1324 die $GO if($c->depth > 0);
1325 }
fbcc39ad 1326 else {
1327 unless ( ref $error ) {
91d08727 1328 no warnings 'uninitialized';
fbcc39ad 1329 chomp $error;
f59def82 1330 my $class = $last->class;
1331 my $name = $last->name;
1332 $error = qq/Caught exception in $class->$name "$error"/;
fbcc39ad 1333 }
fbcc39ad 1334 $c->error($error);
1335 $c->state(0);
1336 }
1337 }
1338 return $c->state;
1339}
1340
7a7d7af5 1341sub _stats_start_execute {
1342 my ( $c, $code ) = @_;
1343
a6724a82 1344 return if ( ( $code->name =~ /^_.*/ )
1345 && ( !$c->config->{show_internal_actions} ) );
7a7d7af5 1346
f3414019 1347 my $action_name = $code->reverse();
1348 $c->counter->{$action_name}++;
7a7d7af5 1349
f3414019 1350 my $action = $action_name;
a6724a82 1351 $action = "/$action" unless $action =~ /->/;
1352
7a7d7af5 1353 # determine if the call was the result of a forward
1354 # this is done by walking up the call stack and looking for a calling
1355 # sub of Catalyst::forward before the eval
1356 my $callsub = q{};
1357 for my $index ( 2 .. 11 ) {
1358 last
1359 if ( ( caller($index) )[0] eq 'Catalyst'
1360 && ( caller($index) )[3] eq '(eval)' );
1361
1362 if ( ( caller($index) )[3] =~ /forward$/ ) {
1363 $callsub = ( caller($index) )[3];
1364 $action = "-> $action";
1365 last;
1366 }
1367 }
1368
f3414019 1369 my $uid = $action_name . $c->counter->{$action_name};
74efc144 1370
a6724a82 1371 # is this a root-level call or a forwarded call?
1372 if ( $callsub =~ /forward$/ ) {
1373
1374 # forward, locate the caller
1375 if ( my $parent = $c->stack->[-1] ) {
69d8f33c 1376 $c->stats->profile(
ac5c933b 1377 begin => $action,
69d8f33c 1378 parent => "$parent" . $c->counter->{"$parent"},
1379 uid => $uid,
1380 );
7a7d7af5 1381 }
1382 else {
1383
a6724a82 1384 # forward with no caller may come from a plugin
69d8f33c 1385 $c->stats->profile(
1386 begin => $action,
1387 uid => $uid,
1388 );
7a7d7af5 1389 }
1390 }
a6724a82 1391 else {
ac5c933b 1392
a6724a82 1393 # root-level call
69d8f33c 1394 $c->stats->profile(
1395 begin => $action,
1396 uid => $uid,
1397 );
a6724a82 1398 }
dc5f035e 1399 return $action;
7a7d7af5 1400
7a7d7af5 1401}
1402
1403sub _stats_finish_execute {
1404 my ( $c, $info ) = @_;
69d8f33c 1405 $c->stats->profile( end => $info );
7a7d7af5 1406}
1407
3d0d6d21 1408=head2 $c->_localize_fields( sub { }, \%keys );
1409
1410=cut
1411
e63bdf38 1412#Why does this exist? This is no longer safe and WILL NOT WORK.
1413# it doesnt seem to be used anywhere. can we remove it?
3d0d6d21 1414sub _localize_fields {
1415 my ( $c, $localized, $code ) = ( @_ );
1416
1417 my $request = delete $localized->{request} || {};
1418 my $response = delete $localized->{response} || {};
ac5c933b 1419
3d0d6d21 1420 local @{ $c }{ keys %$localized } = values %$localized;
1421 local @{ $c->request }{ keys %$request } = values %$request;
1422 local @{ $c->response }{ keys %$response } = values %$response;
1423
1424 $code->();
1425}
1426
b5ecfcf0 1427=head2 $c->finalize
fbcc39ad 1428
e7f1cf73 1429Finalizes the request.
fbcc39ad 1430
1431=cut
1432
1433sub finalize {
1434 my $c = shift;
1435
369c09bc 1436 for my $error ( @{ $c->error } ) {
1437 $c->log->error($error);
1438 }
1439
5050d7a7 1440 # Allow engine to handle finalize flow (for POE)
e63bdf38 1441 my $engine = $c->engine;
1442 if ( my $code = $engine->can('finalize') ) {
1443 $engine->$code($c);
fbcc39ad 1444 }
5050d7a7 1445 else {
fbcc39ad 1446
5050d7a7 1447 $c->finalize_uploads;
fbcc39ad 1448
5050d7a7 1449 # Error
1450 if ( $#{ $c->error } >= 0 ) {
1451 $c->finalize_error;
1452 }
1453
1454 $c->finalize_headers;
fbcc39ad 1455
5050d7a7 1456 # HEAD request
1457 if ( $c->request->method eq 'HEAD' ) {
1458 $c->response->body('');
1459 }
1460
1461 $c->finalize_body;
1462 }
ac5c933b 1463
1464 if ($c->use_stats) {
596677b6 1465 my $elapsed = sprintf '%f', $c->stats->elapsed;
12bf12c0 1466 my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
908e3d9e 1467 $c->log->info(
ac5c933b 1468 "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
908e3d9e 1469 }
fbcc39ad 1470
1471 return $c->response->status;
1472}
1473
b5ecfcf0 1474=head2 $c->finalize_body
fbcc39ad 1475
e7f1cf73 1476Finalizes body.
fbcc39ad 1477
1478=cut
1479
1480sub finalize_body { my $c = shift; $c->engine->finalize_body( $c, @_ ) }
1481
b5ecfcf0 1482=head2 $c->finalize_cookies
fbcc39ad 1483
e7f1cf73 1484Finalizes cookies.
fbcc39ad 1485
1486=cut
1487
147821ea 1488sub finalize_cookies { my $c = shift; $c->engine->finalize_cookies( $c, @_ ) }
fbcc39ad 1489
b5ecfcf0 1490=head2 $c->finalize_error
fbcc39ad 1491
e7f1cf73 1492Finalizes error.
fbcc39ad 1493
1494=cut
1495
1496sub finalize_error { my $c = shift; $c->engine->finalize_error( $c, @_ ) }
1497
b5ecfcf0 1498=head2 $c->finalize_headers
fbcc39ad 1499
e7f1cf73 1500Finalizes headers.
fbcc39ad 1501
1502=cut
1503
1504sub finalize_headers {
1505 my $c = shift;
1506
e63bdf38 1507 my $response = $c->response; #accessor calls can add up?
1508
fbcc39ad 1509 # Check if we already finalized headers
6680c772 1510 return if $response->finalized_headers;
fbcc39ad 1511
1512 # Handle redirects
e63bdf38 1513 if ( my $location = $response->redirect ) {
fbcc39ad 1514 $c->log->debug(qq/Redirecting to "$location"/) if $c->debug;
e63bdf38 1515 $response->header( Location => $location );
a7caa492 1516
e63bdf38 1517 #Moose TODO: we should probably be using a predicate method here ?
1518 if ( !$response->body ) {
39655cdc 1519 # Add a default body if none is already present
e63bdf38 1520 $response->body(
e422816e 1521 qq{<html><body><p>This item has moved <a href="$location">here</a>.</p></body></html>}
39655cdc 1522 );
1523 }
fbcc39ad 1524 }
1525
1526 # Content-Length
e63bdf38 1527 if ( $response->body && !$response->content_length ) {
775878ac 1528
8f62c91a 1529 # get the length from a filehandle
e63bdf38 1530 if ( blessed( $response->body ) && $response->body->can('read') )
197bd788 1531 {
e63bdf38 1532 my $stat = stat $response->body;
3b6a1db1 1533 if ( $stat && $stat->size > 0 ) {
e63bdf38 1534 $response->content_length( $stat->size );
8f62c91a 1535 }
1536 else {
775878ac 1537 $c->log->warn('Serving filehandle without a content-length');
8f62c91a 1538 }
1539 }
1540 else {
b5d7a61f 1541 # everything should be bytes at this point, but just in case
e63bdf38 1542 $response->content_length( bytes::length( $response->body ) );
8f62c91a 1543 }
fbcc39ad 1544 }
1545
1546 # Errors
e63bdf38 1547 if ( $response->status =~ /^(1\d\d|[23]04)$/ ) {
1548 $response->headers->remove_header("Content-Length");
1549 $response->body('');
fbcc39ad 1550 }
1551
1552 $c->finalize_cookies;
1553
1554 $c->engine->finalize_headers( $c, @_ );
1555
1556 # Done
6680c772 1557 $response->finalized_headers(1);
fbcc39ad 1558}
1559
b5ecfcf0 1560=head2 $c->finalize_output
fbcc39ad 1561
1562An alias for finalize_body.
1563
b5ecfcf0 1564=head2 $c->finalize_read
fbcc39ad 1565
e7f1cf73 1566Finalizes the input after reading is complete.
fbcc39ad 1567
1568=cut
1569
1570sub finalize_read { my $c = shift; $c->engine->finalize_read( $c, @_ ) }
1571
b5ecfcf0 1572=head2 $c->finalize_uploads
fbcc39ad 1573
ae1e6b59 1574Finalizes uploads. Cleans up any temporary files.
fbcc39ad 1575
1576=cut
1577
1578sub finalize_uploads { my $c = shift; $c->engine->finalize_uploads( $c, @_ ) }
1579
b5ecfcf0 1580=head2 $c->get_action( $action, $namespace )
fbcc39ad 1581
e7f1cf73 1582Gets an action in a given namespace.
fbcc39ad 1583
1584=cut
1585
684d10ed 1586sub get_action { my $c = shift; $c->dispatcher->get_action(@_) }
fbcc39ad 1587
b5ecfcf0 1588=head2 $c->get_actions( $action, $namespace )
a9dc674c 1589
ae1e6b59 1590Gets all actions of a given name in a namespace and all parent
1591namespaces.
a9dc674c 1592
1593=cut
1594
1595sub get_actions { my $c = shift; $c->dispatcher->get_actions( $c, @_ ) }
1596
f7b672ef 1597=head2 $c->handle_request( $class, @arguments )
fbcc39ad 1598
e7f1cf73 1599Called to handle each HTTP request.
fbcc39ad 1600
1601=cut
1602
1603sub handle_request {
1604 my ( $class, @arguments ) = @_;
1605
1606 # Always expect worst case!
1607 my $status = -1;
1608 eval {
dea1884f 1609 if ($class->debug) {
908e3d9e 1610 my $secs = time - $START || 1;
1611 my $av = sprintf '%.3f', $COUNT / $secs;
1612 my $time = localtime time;
1613 $class->log->info("*** Request $COUNT ($av/s) [$$] [$time] ***");
dea1884f 1614 }
908e3d9e 1615
1616 my $c = $class->prepare(@arguments);
1617 $c->dispatch;
ac5c933b 1618 $status = $c->finalize;
fbcc39ad 1619 };
1620
1621 if ( my $error = $@ ) {
1622 chomp $error;
1623 $class->log->error(qq/Caught exception in engine "$error"/);
1624 }
1625
1626 $COUNT++;
6680c772 1627
1628 if(my $coderef = $class->log->can('_flush')){
1629 $class->log->$coderef();
1630 }
fbcc39ad 1631 return $status;
1632}
1633
b5ecfcf0 1634=head2 $c->prepare( @arguments )
fbcc39ad 1635
ae1e6b59 1636Creates a Catalyst context from an engine-specific request (Apache, CGI,
1637etc.).
fbcc39ad 1638
1639=cut
1640
1641sub prepare {
1642 my ( $class, @arguments ) = @_;
1643
6680c772 1644 # XXX
1645 # After the app/ctxt split, this should become an attribute based on something passed
1646 # into the application.
3cec521a 1647 $class->context_class( ref $class || $class ) unless $class->context_class;
6680c772 1648
1649 my $c = $class->context_class->new({});
1650
1651 # For on-demand data
1652 $c->request->_context($c);
1653 $c->response->_context($c);
fbcc39ad 1654
b6d4ee6e 1655 #surely this is not the most efficient way to do things...
dc5f035e 1656 $c->stats($class->stats_class->new)->enable($c->use_stats);
908e3d9e 1657 if ( $c->debug ) {
ac5c933b 1658 $c->res->headers->header( 'X-Catalyst' => $Catalyst::VERSION );
908e3d9e 1659 }
1660
e63bdf38 1661 #XXX reuse coderef from can
5050d7a7 1662 # Allow engine to direct the prepare flow (for POE)
1663 if ( $c->engine->can('prepare') ) {
1664 $c->engine->prepare( $c, @arguments );
1665 }
1666 else {
1667 $c->prepare_request(@arguments);
1668 $c->prepare_connection;
1669 $c->prepare_query_parameters;
1670 $c->prepare_headers;
1671 $c->prepare_cookies;
1672 $c->prepare_path;
1673
878b821c 1674 # Prepare the body for reading, either by prepare_body
1675 # or the user, if they are using $c->read
1676 $c->prepare_read;
ac5c933b 1677
878b821c 1678 # Parse the body unless the user wants it on-demand
1679 unless ( $c->config->{parse_on_demand} ) {
1680 $c->prepare_body;
1681 }
5050d7a7 1682 }
fbcc39ad 1683
fbcc39ad 1684 my $method = $c->req->method || '';
2f381252 1685 my $path = $c->req->path;
1686 $path = '/' unless length $path;
fbcc39ad 1687 my $address = $c->req->address || '';
1688
e3a13771 1689 $c->log->debug(qq/"$method" request for "$path" from "$address"/)
fbcc39ad 1690 if $c->debug;
1691
e3a13771 1692 $c->prepare_action;
1693
fbcc39ad 1694 return $c;
1695}
1696
b5ecfcf0 1697=head2 $c->prepare_action
fbcc39ad 1698
b4b01a8a 1699Prepares action. See L<Catalyst::Dispatcher>.
fbcc39ad 1700
1701=cut
1702
1703sub prepare_action { my $c = shift; $c->dispatcher->prepare_action( $c, @_ ) }
1704
b5ecfcf0 1705=head2 $c->prepare_body
fbcc39ad 1706
e7f1cf73 1707Prepares message body.
fbcc39ad 1708
1709=cut
1710
1711sub prepare_body {
1712 my $c = shift;
1713
e63bdf38 1714 #Moose TODO: what is _body ??
fbcc39ad 1715 # Do we run for the first time?
1716 return if defined $c->request->{_body};
1717
1718 # Initialize on-demand data
1719 $c->engine->prepare_body( $c, @_ );
1720 $c->prepare_parameters;
1721 $c->prepare_uploads;
1722
1723 if ( $c->debug && keys %{ $c->req->body_parameters } ) {
34d28dfd 1724 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
fbcc39ad 1725 for my $key ( sort keys %{ $c->req->body_parameters } ) {
1726 my $param = $c->req->body_parameters->{$key};
1727 my $value = defined($param) ? $param : '';
8c113188 1728 $t->row( $key,
fbcc39ad 1729 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1730 }
1731 $c->log->debug( "Body Parameters are:\n" . $t->draw );
1732 }
1733}
1734
b5ecfcf0 1735=head2 $c->prepare_body_chunk( $chunk )
4bd82c41 1736
e7f1cf73 1737Prepares a chunk of data before sending it to L<HTTP::Body>.
4bd82c41 1738
b4b01a8a 1739See L<Catalyst::Engine>.
1740
4bd82c41 1741=cut
1742
4f5ebacd 1743sub prepare_body_chunk {
1744 my $c = shift;
4bd82c41 1745 $c->engine->prepare_body_chunk( $c, @_ );
1746}
1747
b5ecfcf0 1748=head2 $c->prepare_body_parameters
fbcc39ad 1749
e7f1cf73 1750Prepares body parameters.
fbcc39ad 1751
1752=cut
1753
1754sub prepare_body_parameters {
1755 my $c = shift;
1756 $c->engine->prepare_body_parameters( $c, @_ );
1757}
1758
b5ecfcf0 1759=head2 $c->prepare_connection
fbcc39ad 1760
e7f1cf73 1761Prepares connection.
fbcc39ad 1762
1763=cut
1764
1765sub prepare_connection {
1766 my $c = shift;
1767 $c->engine->prepare_connection( $c, @_ );
1768}
1769
b5ecfcf0 1770=head2 $c->prepare_cookies
fbcc39ad 1771
e7f1cf73 1772Prepares cookies.
fbcc39ad 1773
1774=cut
1775
1776sub prepare_cookies { my $c = shift; $c->engine->prepare_cookies( $c, @_ ) }
1777
b5ecfcf0 1778=head2 $c->prepare_headers
fbcc39ad 1779
e7f1cf73 1780Prepares headers.
fbcc39ad 1781
1782=cut
1783
1784sub prepare_headers { my $c = shift; $c->engine->prepare_headers( $c, @_ ) }
1785
b5ecfcf0 1786=head2 $c->prepare_parameters
fbcc39ad 1787
e7f1cf73 1788Prepares parameters.
fbcc39ad 1789
1790=cut
1791
1792sub prepare_parameters {
1793 my $c = shift;
1794 $c->prepare_body_parameters;
1795 $c->engine->prepare_parameters( $c, @_ );
1796}
1797
b5ecfcf0 1798=head2 $c->prepare_path
fbcc39ad 1799
e7f1cf73 1800Prepares path and base.
fbcc39ad 1801
1802=cut
1803
1804sub prepare_path { my $c = shift; $c->engine->prepare_path( $c, @_ ) }
1805
b5ecfcf0 1806=head2 $c->prepare_query_parameters
fbcc39ad 1807
e7f1cf73 1808Prepares query parameters.
fbcc39ad 1809
1810=cut
1811
1812sub prepare_query_parameters {
1813 my $c = shift;
1814
1815 $c->engine->prepare_query_parameters( $c, @_ );
1816
1817 if ( $c->debug && keys %{ $c->request->query_parameters } ) {
34d28dfd 1818 my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ 36, 'Value' ] );
fbcc39ad 1819 for my $key ( sort keys %{ $c->req->query_parameters } ) {
1820 my $param = $c->req->query_parameters->{$key};
1821 my $value = defined($param) ? $param : '';
8c113188 1822 $t->row( $key,
fbcc39ad 1823 ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
1824 }
1825 $c->log->debug( "Query Parameters are:\n" . $t->draw );
1826 }
1827}
1828
b5ecfcf0 1829=head2 $c->prepare_read
fbcc39ad 1830
e7f1cf73 1831Prepares the input for reading.
fbcc39ad 1832
1833=cut
1834
1835sub prepare_read { my $c = shift; $c->engine->prepare_read( $c, @_ ) }
1836
b5ecfcf0 1837=head2 $c->prepare_request
fbcc39ad 1838
e7f1cf73 1839Prepares the engine request.
fbcc39ad 1840
1841=cut
1842
1843sub prepare_request { my $c = shift; $c->engine->prepare_request( $c, @_ ) }
1844
b5ecfcf0 1845=head2 $c->prepare_uploads
fbcc39ad 1846
e7f1cf73 1847Prepares uploads.
fbcc39ad 1848
1849=cut
1850
1851sub prepare_uploads {
1852 my $c = shift;
1853
1854 $c->engine->prepare_uploads( $c, @_ );
1855
1856 if ( $c->debug && keys %{ $c->request->uploads } ) {
8c113188 1857 my $t = Text::SimpleTable->new(
34d28dfd 1858 [ 12, 'Parameter' ],
1859 [ 26, 'Filename' ],
8c113188 1860 [ 18, 'Type' ],
1861 [ 9, 'Size' ]
1862 );
fbcc39ad 1863 for my $key ( sort keys %{ $c->request->uploads } ) {
1864 my $upload = $c->request->uploads->{$key};
1865 for my $u ( ref $upload eq 'ARRAY' ? @{$upload} : ($upload) ) {
8c113188 1866 $t->row( $key, $u->filename, $u->type, $u->size );
fbcc39ad 1867 }
1868 }
1869 $c->log->debug( "File Uploads are:\n" . $t->draw );
1870 }
1871}
1872
b5ecfcf0 1873=head2 $c->prepare_write
fbcc39ad 1874
e7f1cf73 1875Prepares the output for writing.
fbcc39ad 1876
1877=cut
1878
1879sub prepare_write { my $c = shift; $c->engine->prepare_write( $c, @_ ) }
1880
b5ecfcf0 1881=head2 $c->request_class
1f9cb7c1 1882
e7f1cf73 1883Returns or sets the request class.
1f9cb7c1 1884
b5ecfcf0 1885=head2 $c->response_class
1f9cb7c1 1886
e7f1cf73 1887Returns or sets the response class.
1f9cb7c1 1888
b5ecfcf0 1889=head2 $c->read( [$maxlength] )
fbcc39ad 1890
ae1e6b59 1891Reads a chunk of data from the request body. This method is designed to
1892be used in a while loop, reading C<$maxlength> bytes on every call.
1893C<$maxlength> defaults to the size of the request if not specified.
fbcc39ad 1894
cc95842f 1895You have to set C<< MyApp->config->{parse_on_demand} >> to use this
ae1e6b59 1896directly.
fbcc39ad 1897
878b821c 1898Warning: If you use read(), Catalyst will not process the body,
1899so you will not be able to access POST parameters or file uploads via
1900$c->request. You must handle all body parsing yourself.
1901
fbcc39ad 1902=cut
1903
1904sub read { my $c = shift; return $c->engine->read( $c, @_ ) }
1905
b5ecfcf0 1906=head2 $c->run
fbcc39ad 1907
1908Starts the engine.
1909
1910=cut
1911
1912sub run { my $c = shift; return $c->engine->run( $c, @_ ) }
1913
b5ecfcf0 1914=head2 $c->set_action( $action, $code, $namespace, $attrs )
fbcc39ad 1915
e7f1cf73 1916Sets an action in a given namespace.
fbcc39ad 1917
1918=cut
1919
1920sub set_action { my $c = shift; $c->dispatcher->set_action( $c, @_ ) }
1921
b5ecfcf0 1922=head2 $c->setup_actions($component)
fbcc39ad 1923
e7f1cf73 1924Sets up actions for a component.
fbcc39ad 1925
1926=cut
1927
1928sub setup_actions { my $c = shift; $c->dispatcher->setup_actions( $c, @_ ) }
1929
b5ecfcf0 1930=head2 $c->setup_components
fbcc39ad 1931
86418559 1932Sets up components. Specify a C<setup_components> config option to pass
1933additional options directly to L<Module::Pluggable>. To add additional
1934search paths, specify a key named C<search_extra> as an array
1935reference. Items in the array beginning with C<::> will have the
18de900e 1936application class name prepended to them.
fbcc39ad 1937
2f381252 1938All components found will also have any
1939L<Devel::InnerPackage|inner packages> loaded and set up as components.
1940Note, that modules which are B<not> an I<inner package> of the main
1941file namespace loaded will not be instantiated as components.
1942
fbcc39ad 1943=cut
1944
1945sub setup_components {
1946 my $class = shift;
1947
18de900e 1948 my @paths = qw( ::Controller ::C ::Model ::M ::View ::V );
1949 my $config = $class->config->{ setup_components };
1950 my $extra = delete $config->{ search_extra } || [];
ac5c933b 1951
18de900e 1952 push @paths, @$extra;
ac5c933b 1953
364d7324 1954 my $locator = Module::Pluggable::Object->new(
18de900e 1955 search_path => [ map { s/^(?=::)/$class/; $_; } @paths ],
1956 %$config
364d7324 1957 );
b94b200c 1958
1959 my @comps = sort { length $a <=> length $b } $locator->plugins;
1960 my %comps = map { $_ => 1 } @comps;
ac5c933b 1961
b94b200c 1962 for my $component ( @comps ) {
dd91afb5 1963
1964 # We pass ignore_loaded here so that overlay files for (e.g.)
1965 # Model::DBI::Schema sub-classes are loaded - if it's in @comps
1966 # we know M::P::O found a file on disk so this is safe
1967
f5a4863c 1968 Catalyst::Utils::ensure_class_loaded( $component, { ignore_loaded => 1 } );
1969 #Class::MOP::load_class($component);
364d7324 1970
1971 my $module = $class->setup_component( $component );
1972 my %modules = (
1973 $component => $module,
1974 map {
1975 $_ => $class->setup_component( $_ )
ac5c933b 1976 } grep {
b94b200c 1977 not exists $comps{$_}
364d7324 1978 } Devel::InnerPackage::list_packages( $component )
1979 );
ac5c933b 1980
364d7324 1981 for my $key ( keys %modules ) {
1982 $class->components->{ $key } = $modules{ $key };
fbcc39ad 1983 }
364d7324 1984 }
1985}
fbcc39ad 1986
364d7324 1987=head2 $c->setup_component
fbcc39ad 1988
364d7324 1989=cut
fbcc39ad 1990
364d7324 1991sub setup_component {
1992 my( $class, $component ) = @_;
fbcc39ad 1993
364d7324 1994 unless ( $component->can( 'COMPONENT' ) ) {
1995 return $component;
1996 }
fbcc39ad 1997
364d7324 1998 my $suffix = Catalyst::Utils::class2classsuffix( $component );
1999 my $config = $class->config->{ $suffix } || {};
fbcc39ad 2000
364d7324 2001 my $instance = eval { $component->COMPONENT( $class, $config ); };
fbcc39ad 2002
2003 if ( my $error = $@ ) {
fbcc39ad 2004 chomp $error;
fbcc39ad 2005 Catalyst::Exception->throw(
364d7324 2006 message => qq/Couldn't instantiate component "$component", "$error"/
2007 );
fbcc39ad 2008 }
2009
364d7324 2010 Catalyst::Exception->throw(
2011 message =>
2012 qq/Couldn't instantiate component "$component", "COMPONENT() didn't return an object-like value"/
84ff88cf 2013 ) unless blessed($instance);
364d7324 2014
2015 return $instance;
fbcc39ad 2016}
2017
b5ecfcf0 2018=head2 $c->setup_dispatcher
fbcc39ad 2019
ae1e6b59 2020Sets up dispatcher.
2021
fbcc39ad 2022=cut
2023
2024sub setup_dispatcher {
2025 my ( $class, $dispatcher ) = @_;
2026
2027 if ($dispatcher) {
2028 $dispatcher = 'Catalyst::Dispatcher::' . $dispatcher;
2029 }
2030
cb69249e 2031 if ( my $env = Catalyst::Utils::env_value( $class, 'DISPATCHER' ) ) {
2032 $dispatcher = 'Catalyst::Dispatcher::' . $env;
fbcc39ad 2033 }
2034
2035 unless ($dispatcher) {
cb0354c6 2036 $dispatcher = $class->dispatcher_class;
fbcc39ad 2037 }
2038
e63bdf38 2039 Class::MOP::load_class($dispatcher);
fbcc39ad 2040
2041 # dispatcher instance
2042 $class->dispatcher( $dispatcher->new );
2043}
2044
b5ecfcf0 2045=head2 $c->setup_engine
fbcc39ad 2046
ae1e6b59 2047Sets up engine.
2048
fbcc39ad 2049=cut
2050
2051sub setup_engine {
2052 my ( $class, $engine ) = @_;
2053
2054 if ($engine) {
2055 $engine = 'Catalyst::Engine::' . $engine;
2056 }
2057
cb69249e 2058 if ( my $env = Catalyst::Utils::env_value( $class, 'ENGINE' ) ) {
2059 $engine = 'Catalyst::Engine::' . $env;
fbcc39ad 2060 }
2061
9b0a3e0f 2062 if ( $ENV{MOD_PERL} ) {
fbcc39ad 2063
2064 # create the apache method
84ff88cf 2065 $class->meta->add_method('apache' => sub { shift->engine->apache });
fbcc39ad 2066
2067 my ( $software, $version ) =
2068 $ENV{MOD_PERL} =~ /^(\S+)\/(\d+(?:[\.\_]\d+)+)/;
2069
2070 $version =~ s/_//g;
2071 $version =~ s/(\.[^.]+)\./$1/g;
2072
2073 if ( $software eq 'mod_perl' ) {
2074
9b0a3e0f 2075 if ( !$engine ) {
22247e54 2076
9b0a3e0f 2077 if ( $version >= 1.99922 ) {
2078 $engine = 'Catalyst::Engine::Apache2::MP20';
2079 }
22247e54 2080
9b0a3e0f 2081 elsif ( $version >= 1.9901 ) {
2082 $engine = 'Catalyst::Engine::Apache2::MP19';
2083 }
22247e54 2084
9b0a3e0f 2085 elsif ( $version >= 1.24 ) {
2086 $engine = 'Catalyst::Engine::Apache::MP13';
2087 }
22247e54 2088
9b0a3e0f 2089 else {
2090 Catalyst::Exception->throw( message =>
2091 qq/Unsupported mod_perl version: $ENV{MOD_PERL}/ );
2092 }
fbcc39ad 2093
fbcc39ad 2094 }
2095
2096 # install the correct mod_perl handler
2097 if ( $version >= 1.9901 ) {
2098 *handler = sub : method {
2099 shift->handle_request(@_);
2100 };
2101 }
2102 else {
2103 *handler = sub ($$) { shift->handle_request(@_) };
2104 }
2105
2106 }
2107
2108 elsif ( $software eq 'Zeus-Perl' ) {
2109 $engine = 'Catalyst::Engine::Zeus';
2110 }
2111
2112 else {
2113 Catalyst::Exception->throw(
2114 message => qq/Unsupported mod_perl: $ENV{MOD_PERL}/ );
2115 }
2116 }
2117
2118 unless ($engine) {
cb0354c6 2119 $engine = $class->engine_class;
fbcc39ad 2120 }
2121
e63bdf38 2122 Class::MOP::load_class($engine);
2123 #unless (Class::Inspector->loaded($engine)) {
2124 # require Class::Inspector->filename($engine);
2125 #}
0e7f5826 2126
d54484bf 2127 # check for old engines that are no longer compatible
2128 my $old_engine;
0e7f5826 2129 if ( $engine->isa('Catalyst::Engine::Apache')
2130 && !Catalyst::Engine::Apache->VERSION )
d54484bf 2131 {
2132 $old_engine = 1;
2133 }
0e7f5826 2134
d54484bf 2135 elsif ( $engine->isa('Catalyst::Engine::Server::Base')
0e7f5826 2136 && Catalyst::Engine::Server->VERSION le '0.02' )
d54484bf 2137 {
2138 $old_engine = 1;
2139 }
0e7f5826 2140
2141 elsif ($engine->isa('Catalyst::Engine::HTTP::POE')
2142 && $engine->VERSION eq '0.01' )
d54484bf 2143 {
2144 $old_engine = 1;
2145 }
0e7f5826 2146
2147 elsif ($engine->isa('Catalyst::Engine::Zeus')
2148 && $engine->VERSION eq '0.01' )
d54484bf 2149 {
2150 $old_engine = 1;
2151 }
fbcc39ad 2152
d54484bf 2153 if ($old_engine) {
2154 Catalyst::Exception->throw( message =>
0e7f5826 2155 qq/Engine "$engine" is not supported by this version of Catalyst/
d54484bf 2156 );
2157 }
0e7f5826 2158
fbcc39ad 2159 # engine instance
2160 $class->engine( $engine->new );
2161}
2162
b5ecfcf0 2163=head2 $c->setup_home
fbcc39ad 2164
ae1e6b59 2165Sets up the home directory.
2166
fbcc39ad 2167=cut
2168
2169sub setup_home {
2170 my ( $class, $home ) = @_;
2171
cb69249e 2172 if ( my $env = Catalyst::Utils::env_value( $class, 'HOME' ) ) {
2173 $home = $env;
fbcc39ad 2174 }
2175
b6d4ee6e 2176 $home ||= Catalyst::Utils::home($class);
fbcc39ad 2177
2178 if ($home) {
e63bdf38 2179 #I remember recently being scolded for assigning config values like this
fbcc39ad 2180 $class->config->{home} ||= $home;
a738ab68 2181 $class->config->{root} ||= Path::Class::Dir->new($home)->subdir('root');
fbcc39ad 2182 }
2183}
2184
b5ecfcf0 2185=head2 $c->setup_log
fbcc39ad 2186
ae1e6b59 2187Sets up log.
2188
fbcc39ad 2189=cut
2190
2191sub setup_log {
2192 my ( $class, $debug ) = @_;
2193
2194 unless ( $class->log ) {
2195 $class->log( Catalyst::Log->new );
2196 }
af3ff00e 2197
cb69249e 2198 my $env_debug = Catalyst::Utils::env_value( $class, 'DEBUG' );
2199 if ( defined($env_debug) ? $env_debug : $debug ) {
84ff88cf 2200 $class->meta->add_method('debug' => sub { 1 });
fbcc39ad 2201 $class->log->debug('Debug messages enabled');
2202 }
2203}
2204
b5ecfcf0 2205=head2 $c->setup_plugins
fbcc39ad 2206
ae1e6b59 2207Sets up plugins.
2208
fbcc39ad 2209=cut
2210
dc5f035e 2211=head2 $c->setup_stats
2212
2213Sets up timing statistics class.
2214
2215=cut
2216
2217sub setup_stats {
2218 my ( $class, $stats ) = @_;
2219
2220 Catalyst::Utils::ensure_class_loaded($class->stats_class);
2221
2222 my $env = Catalyst::Utils::env_value( $class, 'STATS' );
2223 if ( defined($env) ? $env : ($stats || $class->debug ) ) {
84ff88cf 2224 $class->meta->add_method('use_stats' => sub { 1 });
b01f0c69 2225 $class->log->debug('Statistics enabled');
dc5f035e 2226 }
2227}
2228
2229
ac5c933b 2230=head2 $c->registered_plugins
836e1134 2231
2232Returns a sorted list of the plugins which have either been stated in the
2233import list or which have been added via C<< MyApp->plugin(@args); >>.
2234
2235If passed a given plugin name, it will report a boolean value indicating
2236whether or not that plugin is loaded. A fully qualified name is required if
2237the plugin name does not begin with C<Catalyst::Plugin::>.
2238
2239 if ($c->registered_plugins('Some::Plugin')) {
2240 ...
2241 }
2242
2243=cut
fbcc39ad 2244
836e1134 2245{
97b58e17 2246
2247 sub registered_plugins {
836e1134 2248 my $proto = shift;
197bd788 2249 return sort keys %{ $proto->_plugins } unless @_;
836e1134 2250 my $plugin = shift;
d0d4d785 2251 return 1 if exists $proto->_plugins->{$plugin};
2252 return exists $proto->_plugins->{"Catalyst::Plugin::$plugin"};
836e1134 2253 }
fbcc39ad 2254
836e1134 2255 sub _register_plugin {
2256 my ( $proto, $plugin, $instant ) = @_;
2257 my $class = ref $proto || $proto;
fbcc39ad 2258
dd91afb5 2259 # no ignore_loaded here, the plugin may already have been
2260 # defined in memory and we don't want to error on "no file" if so
2261
b6d4ee6e 2262 Class::MOP::load_class( $plugin );
fbcc39ad 2263
197bd788 2264 $proto->_plugins->{$plugin} = 1;
836e1134 2265 unless ($instant) {
fbcc39ad 2266 no strict 'refs';
5fb67d52 2267 if( $class->can('meta') ){
2268 my @superclasses = ($plugin, $class->meta->superclasses );
2269 $class->meta->superclasses(@superclasses);
2270 } else {
2271 unshift @{"$class\::ISA"}, $plugin;
2272 }
fbcc39ad 2273 }
836e1134 2274 return $class;
2275 }
2276
2277 sub setup_plugins {
2278 my ( $class, $plugins ) = @_;
2279
d0d4d785 2280 $class->_plugins( {} ) unless $class->_plugins;
836e1134 2281 $plugins ||= [];
2282 for my $plugin ( reverse @$plugins ) {
2283
2284 unless ( $plugin =~ s/\A\+// ) {
2285 $plugin = "Catalyst::Plugin::$plugin";
2286 }
2287
2288 $class->_register_plugin($plugin);
2289 }
fbcc39ad 2290 }
2291}
2292
b5ecfcf0 2293=head2 $c->stack
8767c5a3 2294
86418559 2295Returns an arrayref of the internal execution stack (actions that are
2296currently executing).
8767c5a3 2297
dc5f035e 2298=head2 $c->stats_class
2299
2300Returns or sets the stats (timing statistics) class.
2301
2302=head2 $c->use_stats
2303
2304Returns 1 when stats collection is enabled. Stats collection is enabled
2305when the -Stats options is set, debug is on or when the <MYAPP>_STATS
2306environment variable is set.
2307
2308Note that this is a static method, not an accessor and should be overloaded
2309by declaring "sub use_stats { 1 }" in your MyApp.pm, not by calling $c->use_stats(1).
2310
2311=cut
2312
2313sub use_stats { 0 }
2314
2315
b5ecfcf0 2316=head2 $c->write( $data )
fbcc39ad 2317
ae1e6b59 2318Writes $data to the output stream. When using this method directly, you
2319will need to manually set the C<Content-Length> header to the length of
2320your output data, if known.
fbcc39ad 2321
2322=cut
2323
4f5ebacd 2324sub write {
2325 my $c = shift;
2326
2327 # Finalize headers if someone manually writes output
2328 $c->finalize_headers;
2329
2330 return $c->engine->write( $c, @_ );
2331}
fbcc39ad 2332
b5ecfcf0 2333=head2 version
bf88a181 2334
ae1e6b59 2335Returns the Catalyst version number. Mostly useful for "powered by"
2336messages in template systems.
bf88a181 2337
2338=cut
2339
2340sub version { return $Catalyst::VERSION }
2341
b0bb11ec 2342=head1 INTERNAL ACTIONS
2343
ae1e6b59 2344Catalyst uses internal actions like C<_DISPATCH>, C<_BEGIN>, C<_AUTO>,
2345C<_ACTION>, and C<_END>. These are by default not shown in the private
3e705254 2346action table, but you can make them visible with a config parameter.
b0bb11ec 2347
2348 MyApp->config->{show_internal_actions} = 1;
2349
d2ee9760 2350=head1 CASE SENSITIVITY
2351
3e705254 2352By default Catalyst is not case sensitive, so C<MyApp::C::FOO::Bar> is
ae1e6b59 2353mapped to C</foo/bar>. You can activate case sensitivity with a config
3e705254 2354parameter.
d2ee9760 2355
2356 MyApp->config->{case_sensitive} = 1;
2357
3e705254 2358This causes C<MyApp::C::Foo::Bar> to map to C</Foo/Bar>.
fbcc39ad 2359
2360=head1 ON-DEMAND PARSER
2361
2362The request body is usually parsed at the beginning of a request,
878b821c 2363but if you want to handle input yourself, you can enable on-demand
2364parsing with a config parameter.
fbcc39ad 2365
2366 MyApp->config->{parse_on_demand} = 1;
ac5c933b 2367
fbcc39ad 2368=head1 PROXY SUPPORT
2369
ae1e6b59 2370Many production servers operate using the common double-server approach,
2371with a lightweight frontend web server passing requests to a larger
2372backend server. An application running on the backend server must deal
2373with two problems: the remote user always appears to be C<127.0.0.1> and
2374the server's hostname will appear to be C<localhost> regardless of the
2375virtual host that the user connected through.
fbcc39ad 2376
ae1e6b59 2377Catalyst will automatically detect this situation when you are running
2378the frontend and backend servers on the same machine. The following
2379changes are made to the request.
fbcc39ad 2380
ac5c933b 2381 $c->req->address is set to the user's real IP address, as read from
ae1e6b59 2382 the HTTP X-Forwarded-For header.
ac5c933b 2383
ae1e6b59 2384 The host value for $c->req->base and $c->req->uri is set to the real
2385 host, as read from the HTTP X-Forwarded-Host header.
fbcc39ad 2386
3e705254 2387Obviously, your web server must support these headers for this to work.
fbcc39ad 2388
ae1e6b59 2389In a more complex server farm environment where you may have your
2390frontend proxy server(s) on different machines, you will need to set a
2391configuration option to tell Catalyst to read the proxied data from the
2392headers.
fbcc39ad 2393
2394 MyApp->config->{using_frontend_proxy} = 1;
ac5c933b 2395
fbcc39ad 2396If you do not wish to use the proxy support at all, you may set:
d1a31ac6 2397
fbcc39ad 2398 MyApp->config->{ignore_frontend_proxy} = 1;
2399
2400=head1 THREAD SAFETY
2401
86418559 2402Catalyst has been tested under Apache 2's threading C<mpm_worker>,
2403C<mpm_winnt>, and the standalone forking HTTP server on Windows. We
2404believe the Catalyst core to be thread-safe.
fbcc39ad 2405
2406If you plan to operate in a threaded environment, remember that all other
3e705254 2407modules you are using must also be thread-safe. Some modules, most notably
2408L<DBD::SQLite>, are not thread-safe.
d1a31ac6 2409
3cb1db8c 2410=head1 SUPPORT
2411
2412IRC:
2413
4eaf7c88 2414 Join #catalyst on irc.perl.org.
3cb1db8c 2415
3e705254 2416Mailing Lists:
3cb1db8c 2417
2418 http://lists.rawmode.org/mailman/listinfo/catalyst
2419 http://lists.rawmode.org/mailman/listinfo/catalyst-dev
1985c30b 2420
432d507d 2421Web:
2422
2423 http://catalyst.perl.org
2424
0ef52a96 2425Wiki:
2426
2427 http://dev.catalyst.perl.org
2428
fc7ec1d9 2429=head1 SEE ALSO
2430
829a28ca 2431=head2 L<Task::Catalyst> - All you need to start with Catalyst
2432
b5ecfcf0 2433=head2 L<Catalyst::Manual> - The Catalyst Manual
e7f1cf73 2434
b5ecfcf0 2435=head2 L<Catalyst::Component>, L<Catalyst::Base> - Base classes for components
61b1e958 2436
b5ecfcf0 2437=head2 L<Catalyst::Engine> - Core engine
61b1e958 2438
b5ecfcf0 2439=head2 L<Catalyst::Log> - Log class.
61b1e958 2440
b5ecfcf0 2441=head2 L<Catalyst::Request> - Request object
61b1e958 2442
b5ecfcf0 2443=head2 L<Catalyst::Response> - Response object
61b1e958 2444
b5ecfcf0 2445=head2 L<Catalyst::Test> - The test suite.
fc7ec1d9 2446
2f381252 2447=head1 PROJECT FOUNDER
2448
2449sri: Sebastian Riedel <sri@cpan.org>
fc7ec1d9 2450
2f381252 2451=head1 CONTRIBUTORS
15f0b5b7 2452
2f381252 2453abw: Andy Wardley
fbcc39ad 2454
2f381252 2455acme: Leon Brocard <leon@astray.com>
33108eaf 2456
f4a57de4 2457Andrew Bramble
2458
15f0b5b7 2459Andrew Ford
2460
2461Andrew Ruthven
2462
2f381252 2463andyg: Andy Grundman <andy@hybridized.org>
fbcc39ad 2464
2f381252 2465audreyt: Audrey Tang
15f0b5b7 2466
2f381252 2467bricas: Brian Cassidy <bricas@cpan.org>
0cf56dbc 2468
2f381252 2469chansen: Christian Hansen
6aaa1c60 2470
2f381252 2471chicks: Christopher Hicks
15f0b5b7 2472
2f381252 2473dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
15f0b5b7 2474
2f381252 2475Drew Taylor
15f0b5b7 2476
2f381252 2477esskar: Sascha Kiefer
0ef52a96 2478
2f381252 2479fireartist: Carl Franks <cfranks@cpan.org>
15f0b5b7 2480
2f381252 2481gabb: Danijel Milicevic
61bef238 2482
15f0b5b7 2483Gary Ashton Jones
2484
2485Geoff Richards
2486
e4cc83b2 2487ilmari: Dagfinn Ilmari Mannsåker <ilmari@ilmari.org>
2488
2f381252 2489jcamacho: Juan Camacho
fbcc39ad 2490
15f0b5b7 2491Jody Belka
2492
2493Johan Lindstrom
2494
2f381252 2495jon: Jon Schutz <jjschutz@cpan.org>
15f0b5b7 2496
2f381252 2497marcus: Marcus Ramberg <mramberg@cpan.org>
15f0b5b7 2498
2f381252 2499miyagawa: Tatsuhiko Miyagawa <miyagawa@bulknews.net>
15f0b5b7 2500
2f381252 2501mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
15f0b5b7 2502
2f381252 2503mugwump: Sam Vilain
71c3bcc3 2504
2f381252 2505naughton: David Naughton
a727119f 2506
2f381252 2507ningu: David Kamholz <dkamholz@cpan.org>
1cf1c56a 2508
2f381252 2509nothingmuch: Yuval Kogman <nothingmuch@woobling.org>
9c71d51d 2510
2f381252 2511numa: Dan Sully <daniel@cpan.org>
fc7ec1d9 2512
2f381252 2513obra: Jesse Vincent
2514
2515omega: Andreas Marienborg
51f0308d 2516
2f381252 2517phaylon: Robert Sedlacek <phaylon@dunkelheit.at>
bdcb95ef 2518
6dae3eef 2519rafl: Florian Ragwitz <rafl@debian.org>
2520
2f381252 2521sky: Arthur Bergman
2522
2523the_jester: Jesse Sheidlower
2524
2525Ulf Edvinsson
51f0308d 2526
2f381252 2527willert: Sebastian Willert <willert@cpan.org>
51f0308d 2528
fc7ec1d9 2529=head1 LICENSE
2530
9ce5ab63 2531This library is free software, you can redistribute it and/or modify it under
41ca9ba7 2532the same terms as Perl itself.
fc7ec1d9 2533
2534=cut
2535
4090e3bb 2536no Moose;
2537
46d0346d 2538__PACKAGE__->meta->make_immutable;
2539
fc7ec1d9 25401;