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