Skip to content

Commit

Permalink
fix bug in Mojolicious::Validator::Validation where empty optional
Browse files Browse the repository at this point in the history
values were not being handled correctly (closes #824)
  • Loading branch information
kraih committed Aug 7, 2015
1 parent 5a399f7 commit 0bfc963
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 18 deletions.
4 changes: 3 additions & 1 deletion Changes
@@ -1,5 +1,7 @@

6.15 2015-07-17
6.15 2015-08-07
- Fixed bug in Mojolicious::Validator::Validation where empty optional values
were not being handled correctly.
- Fixed warnings in Mojo::DOM.

6.14 2015-07-12
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Headers.pm
Expand Up @@ -7,7 +7,7 @@ has max_line_size => sub { $ENV{MOJO_MAX_LINE_SIZE} || 8192 };
has max_lines => sub { $ENV{MOJO_MAX_LINES} || 100 };

# Common headers
my %NORMALCASE = map { lc($_) => $_ } (
my %NORMALCASE = map { lc() => $_ } (
qw(Accept Accept-Charset Accept-Encoding Accept-Language Accept-Ranges),
qw(Access-Control-Allow-Origin Allow Authorization Cache-Control Connection),
qw(Content-Disposition Content-Encoding Content-Language Content-Length),
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojo/JSON.pm
Expand Up @@ -161,11 +161,11 @@ sub _decode_string {

# High surrogate
($ord & 0xfc00) == 0xd800
or pos($_) = $pos + pos($str), _throw('Missing high-surrogate');
or pos = $pos + pos($str), _throw('Missing high-surrogate');

# Low surrogate
$str =~ /\G\\u([Dd][C-Fc-f]..)/gc
or pos($_) = $pos + pos($str), _throw('Missing low-surrogate');
or pos = $pos + pos($str), _throw('Missing low-surrogate');

$ord = 0x10000 + ($ord - 0xd800) * 0x400 + (hex($1) - 0xdc00);
}
Expand Down
27 changes: 16 additions & 11 deletions lib/Mojolicious/Validator/Validation.pm
Expand Up @@ -63,27 +63,32 @@ sub has_error { $_[1] ? exists $_[0]{error}{$_[1]} : !!keys %{$_[0]{error}} }

sub is_valid { exists $_[0]->output->{$_[1] // $_[0]->topic} }

sub optional {
my ($self, $name) = @_;

my $input = $self->input->{$name};
my @input = ref $input eq 'ARRAY' ? @$input : $input;
$self->output->{$name} = $input
unless grep { !defined($_) || !length($_) } @input;

return $self->topic($name);
}
sub optional { shift->_copy(shift, 0) }

sub param { shift->every_param(shift)->[-1] }

sub passed { [sort keys %{shift->output}] }

sub required {
my ($self, $name) = @_;
return $self if $self->optional($name)->is_valid;
return $self if $self->_copy($name, 1)->is_valid;
return $self->error($name => ['required']);
}

sub _copy {
my ($self, $name, $all) = @_;

my $input = $self->input->{$name};
my @input = ref $input eq 'ARRAY' ? @$input : $input;
my @output = grep { defined && length } @input;

if ($all && @output && @input == @output) { $self->output->{$name} = $input }
elsif (!$all && @output > 1) { $self->output->{$name} = \@output }
elsif (!$all && @output) { $self->output->{$name} = $output[0] }

return $self->topic($name);
}

1;

=encoding utf8
Expand Down
9 changes: 6 additions & 3 deletions t/mojolicious/validation_lite_app.t
Expand Up @@ -157,10 +157,13 @@ is_deeply $validation->failed, ['bar'], 'right names';
# Multiple empty values
$validation = $t->app->validation;
ok !$validation->has_data, 'no data';
$validation->input({foo => ['', 'bar', '']});
$validation->input({foo => ['', 'bar', ''], bar => ['', 'baz', '']});
ok $validation->has_data, 'has data';
ok $validation->optional('bar')->is_valid, 'valid';
is_deeply $validation->output, {bar => 'baz'}, 'right result';
ok !$validation->has_error, 'no error';
ok !$validation->required('foo')->is_valid, 'not valid';
is_deeply $validation->output, {}, 'right result';
is_deeply $validation->output, {bar => 'baz'}, 'right result';
ok $validation->has_error, 'has error';
is_deeply $validation->error('foo'), ['required'], 'right error';

Expand Down Expand Up @@ -223,7 +226,7 @@ $t->get_ok('/' => form => {foo => '☃☃'})->status_is(200)
->element_exists('input[type="password"]');

# Validation failed for required fields
$t->post_ok('/' => form => {foo => 'no'})->status_is(200)
$t->post_ok('/' => form => {foo => ['no']})->status_is(200)
->text_is('div:root' => 'in 1')
->text_is('label.custom.field-with-error[for="foo"]' => '<Foo>')
->element_exists('input.custom.field-with-error[type="text"][value="no"]')
Expand Down

0 comments on commit 0bfc963

Please sign in to comment.