X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst.pm;h=602316a9c0346b2eb779f673a4fd85bf296a3ac9;hp=b79df558394be9259cfbf148e9640a770172a096;hb=163b3de6693e8c44dbe24cfc79cc3cf300610ed8;hpb=f176d1c8ec4d1b119ca573a9c2e2aa5fc3a3324d diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm index b79df55..602316a 100644 --- a/lib/Catalyst.pm +++ b/lib/Catalyst.pm @@ -180,7 +180,7 @@ sub composed_stats_class { __PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC); # Remember to update this in Catalyst::Runtime as well! -our $VERSION = '5.90099_001'; +our $VERSION = '5.90104'; $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases sub import { @@ -606,13 +606,17 @@ sub error { return $c->{error} || []; } - =head2 $c->state Contains the return value of the last executed action. Note that << $c->state >> operates in a scalar context which means that all values it returns are scalar. +Please note that if an action throws an exception, the value of state +should no longer be considered the return if the last action. It is generally +going to be 0, which indicates an error state. Examine $c->error for error +details. + =head2 $c->clear_errors Clear errors. You probably don't want to clear the errors unless you are @@ -640,22 +644,42 @@ sub has_errors { scalar(@{shift->error}) ? 1:0 } =head2 $c->last_error Returns the most recent error in the stack (the one most recently added...) -or nothing if there are no errors. +or nothing if there are no errors. This does not modify the contents of the +error stack. =cut -sub last_error { my ($err, @errs) = @{shift->error}; return $err } +sub last_error { + my (@errs) = @{shift->error}; + return scalar(@errs) ? $errs[-1]: undef; +} =head2 shift_errors -shifts the most recently added error off the error stack and returns if. Returns +shifts the most recently added error off the error stack and returns it. Returns nothing if there are no more errors. =cut sub shift_errors { my ($self) = @_; - my ($err, @errors) = @{$self->error}; + my @errors = @{$self->error}; + my $err = shift(@errors); + $self->{error} = \@errors; + return $err; +} + +=head2 pop_errors + +pops the most recently added error off the error stack and returns it. Returns +nothing if there are no more errors. + +=cut + +sub pop_errors { + my ($self) = @_; + my @errors = @{$self->error}; + my $err = pop(@errors); $self->{error} = \@errors; return $err; } @@ -787,6 +811,11 @@ sub controller { my $comps = $c->components; my $check = $appclass."::Controller::".$name; return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; + foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { + next unless $path =~ /.*::Controller/; + $check = $path."::".$name; + return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; + } } my @result = $c->_comp_search_prefixes( $name, qw/Controller C/ ); return map { $c->_filter_component( $_, @args ) } @result if ref $name; @@ -826,6 +855,11 @@ sub model { my $comps = $c->components; my $check = $appclass."::Model::".$name; return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; + foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { + next unless $path =~ /.*::Model/; + $check = $path."::".$name; + return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; + } } my @result = $c->_comp_search_prefixes( $name, qw/Model M/ ); return map { $c->_filter_component( $_, @args ) } @result if ref $name; @@ -890,6 +924,11 @@ sub view { else { $c->log->warn( "Attempted to use view '$check', but does not exist" ); } + foreach my $path (@{$appclass->config->{ setup_components }->{ search_extra }}) { + next unless $path =~ /.*::View/; + $check = $path."::".$name; + return $c->_filter_component( $comps->{$check}, @args ) if exists $comps->{$check}; + } } my @result = $c->_comp_search_prefixes( $name, qw/View V/ ); return map { $c->_filter_component( $_, @args ) } @result if ref $name; @@ -1464,11 +1503,11 @@ sub setup_finalize { $class->setup_finished(1); } -=head2 $c->uri_for( $path?, @args?, \%query_values? ) +=head2 $c->uri_for( $path?, @args?, \%query_values?, \$fragment? ) -=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values? ) +=head2 $c->uri_for( $action, \@captures?, @args?, \%query_values?, \$fragment? ) -=head2 $c->uri_for( $action, [@captures, @args], \%query_values? ) +=head2 $c->uri_for( $action, [@captures, @args], \%query_values?, \$fragment? ) Constructs an absolute L object based on the application root, the provided path, and the additional arguments and query parameters provided. @@ -1486,6 +1525,15 @@ relative to the application root (if it does). It is then merged with C<< $c->request->base >>; any C<@args> are appended as additional path components; and any C<%query_values> are appended as C parameters. +B If you are using this 'stringy' first argument, we skip encoding and +allow you to declare something like: + + $c->uri_for('/foo/bar#baz') + +Where 'baz' is a URI fragment. We consider this first argument string to be +'expert' mode where you are expected to create a valid URL and we for the most +part just pass it through without a lot of internal effort to escape and encode. + If the first argument is a L it represents an action which will have its path resolved using C<< $c->dispatcher->uri_for_action >>. The optional C<\@captures> argument (an arrayref) allows passing the captured @@ -1528,11 +1576,24 @@ sub uri_for { $path .= '/'; } - undef($path) if (defined $path && $path eq ''); + my $fragment = ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? pop @args : undef ); + + unless(blessed $path) { + if (defined($path) and $path =~ s/#(.+)$//) { + if(defined($1) and $fragment) { + carp "Abiguious fragment declaration: You cannot define a fragment in '$path' and as an argument '$fragment'"; + } + if(defined($1)) { + $fragment = $1; + } + } + } my $params = ( scalar @args && ref $args[$#args] eq 'HASH' ? pop @args : {} ); + undef($path) if (defined $path && $path eq ''); + carp "uri_for called with undef argument" if grep { ! defined $_ } @args; my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef; @@ -1611,7 +1672,6 @@ sub uri_for { } my $query = ''; - if (my @keys = keys %$params) { # somewhat lifted from URI::_query's query_form $query = '?'.join('&', map { @@ -1640,7 +1700,16 @@ sub uri_for { $base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go; $args = encode_utf8 $args; $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go; - + + if(defined $fragment) { + if(blessed $path) { + $fragment = encode_utf8(${$fragment}); + $fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go; + $fragment =~ s/ /+/g; + } + $query .= "#$fragment"; + } + my $res = bless(\"${base}${args}${query}", $class); $res; } @@ -1936,7 +2005,7 @@ via $c->error. sub execute { my ( $c, $class, $code ) = @_; $class = $c->component($class) || $class; - $c->state(0); + #$c->state(0); if ( $c->depth >= $RECURSION ) { my $action = $code->reverse(); @@ -1988,7 +2057,7 @@ sub execute { } $c->error($error); } - $c->state(0); + #$c->state(0); } return $c->state; } @@ -2335,7 +2404,6 @@ sub prepare { my $c = $class->context_class->new({ $uploadtmp ? (_uploadtmp => $uploadtmp) : ()}); $c->response->_context($c); - $c->stats($class->stats_class->new)->enable($c->use_stats); if ( $c->debug || $c->config->{enable_catalyst_header} ) { @@ -2762,7 +2830,7 @@ We try each possible role in turn (and throw an error if none load) MyApp::TraitFor::Request::Foo Catalyst::TraitFor::Request::Foo -The namespace part 'TraitFor::Request' was choosen to assist in backwards +The namespace part 'TraitFor::Request' was chosen to assist in backwards compatibility with L which previously provided these features in a stand alone package. @@ -2793,7 +2861,7 @@ We try each possible role in turn (and throw an error if none load) MyApp::TraitFor::Response::Foo Catalyst::TraitFor::Responset::Foo -The namespace part 'TraitFor::Response' was choosen to assist in backwards +The namespace part 'TraitFor::Response' was chosen to assist in backwards compatibility with L which previously provided these features in a stand alone package. @@ -3040,7 +3108,7 @@ sub locate_components { my $config = shift; my @paths = qw( ::M ::Model ::V ::View ::C ::Controller ); - my $extra = delete $config->{ search_extra } || []; + my $extra = $config->{ search_extra } || []; unshift @paths, @$extra; @@ -3981,7 +4049,7 @@ We try each possible role in turn (and throw an error if none load) MyApp::TraitFor::Stats::Foo Catalyst::TraitFor::Stats::Foo -The namespace part 'TraitFor::Stats' was choosen to assist in backwards +The namespace part 'TraitFor::Stats' was chosen to assist in backwards compatibility with L which previously provided these features in a stand alone package. @@ -4195,7 +4263,7 @@ backwardly compatible). C -When creating body parameters from a POST, if we run into a multpart POST +When creating body parameters from a POST, if we run into a multipart POST that does not contain uploads, but instead contains inlined complex data (very uncommon) we cannot reliably convert that into field => value pairs. So instead we create an instance of L. If this causes @@ -4217,9 +4285,9 @@ parameter to true. C If true, then do not try to character decode any wide characters in your -request URL query or keywords. Most readings of the relevent specifications +request URL query or keywords. Most readings of the relevant specifications suggest these should be UTF-* encoded, which is the default that L -will use, hwoever if you are creating a lot of URLs manually or have external +will use, however if you are creating a lot of URLs manually or have external evil clients, this might cause you trouble. If you find the changes introduced in Catalyst version 5.90080+ break some of your query code, you may disable the UTF-8 decoding globally using this configuration. @@ -4232,7 +4300,7 @@ C C By default we decode query and keywords in your request URL using UTF-8, which -is our reading of the relevent specifications. This setting allows one to +is our reading of the relevant specifications. This setting allows one to specify a fixed value for how to decode your query. You might need this if you are doing a lot of custom encoding of your URLs and not using UTF-8. @@ -4269,19 +4337,19 @@ C - See L. C -An arrayref of Ls that get componsed into your stats class. +An arrayref of Ls that get composed into your stats class. =item * C -An arrayref of Ls that get componsed into your request class. +An arrayref of Ls that get composed into your request class. =item * C -An arrayref of Ls that get componsed into your response class. +An arrayref of Ls that get composed into your response class. =item *