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