Data-Validation
view release on metacpan or search on metacpan
lib/Data/Validation.pm view on Meta::CPAN
'>' => sub { $_[ 0 ] > $_[ 1 ] },
'>=' => sub { $_[ 0 ] >= $_[ 1 ] },
'<' => sub { $_[ 0 ] < $_[ 1 ] },
'<=' => sub { $_[ 0 ] <= $_[ 1 ] }, };
};
my $_get_methods = sub {
return split SPC, $_[ 0 ] // NUL;
};
my $_should_compare = sub {
return first { $_ eq 'compare' } $_get_methods->( $_[ 0 ]->{validate} );
};
# Private methods
my $_filter = sub {
my ($self, $filters, $id, $v) = @_;
for my $method ($_get_methods->( $filters )) {
my $attr = { %{ $self->filters->{ $id } // {} }, method => $method, };
my $dvf_obj = Data::Validation::Filters->new_from_method( $attr );
$v = $dvf_obj->filter( $v );
}
return $v;
};
my $_compare_fields = sub {
my ($self, $prefix, $form, $lhs_name) = @_;
my $id = $prefix.$lhs_name;
my $constraint = $self->constraints->{ $id } // {};
my $rhs_name = $constraint->{other_field}
or throw 'Constraint [_1] has no comparison field', [ $id ];
my $op = $constraint->{operator} // 'eq';
my $compare = $_comparisons->()->{ $op }
or throw 'Constraint [_1] unknown comparison operator [_2]', [ $id, $op ];
my $lhs = $form->{ $lhs_name } // NUL;
my $rhs = $form->{ $rhs_name } // NUL;
$compare->( $lhs, $rhs ) and return;
$lhs_name = $self->fields->{ $prefix.$lhs_name }->{label} // $lhs_name;
$rhs_name = $self->fields->{ $prefix.$rhs_name }->{label} // $rhs_name;
throw FieldComparison, [ $lhs_name, $op, $rhs_name ], level => $self->level;
};
my $_validate = sub {
my ($self, $valids, $id, $v) = @_;
$valids !~ m{ isMandatory }mx and (not defined $v or not length $v)
and return;
my $params = $self->constraints->{ $id } // {};
my $label = $self->fields->{ $id }->{label} // $id;
for my $methods (grep { $_ ne 'compare' } $_get_methods->( $valids )) {
my @fails;
for my $method (split m{ [|] }mx, $methods) {
my $constraint = Data::Validation::Constraints->new_from_method
( { %{ $params }, method => $method, } );
(my $class = $method) =~ s{ \A is }{}mx;
if ($constraint->validate( $v )) { @fails = (); last }
push @fails, $class;
}
@fails == 1 and throw sub { $fails[ 0 ] }, [ $label ],
constraints => $params, level => $self->level;
@fails > 1 and throw 'Field [_1] is none of [_2]',
[ $label, join ' | ', @fails ],
level => $self->level;
}
return;
};
# Public methods
sub check_form { # Validate all fields on a form by repeated calling check_field
my ($self, $prefix, $form) = @_; my @errors = (); $prefix ||= NUL;
($form and ref $form eq HASH) or throw 'Form parameter not a hash ref';
for my $name (sort keys %{ $form }) {
my $id = $prefix.$name; my $conf = $self->fields->{ $id };
($conf and ($conf->{filters} or $conf->{validate})) or next;
try {
$form->{ $name } = $self->check_field( $id, $form->{ $name } );
$_should_compare->( $conf )
and $self->$_compare_fields( $prefix, $form, $name );
}
catch { push @errors, $_ };
}
@errors and throw ValidationErrors, \@errors, level => $self->level;
return $form;
}
sub check_field { # Validate a single form field value
my ($self, $id, $v) = @_; my $conf;
unless ($id and $conf = $self->fields->{ $id }
and ($conf->{filters} or $conf->{validate})) {
throw 'Field [_1] validation configuration not found', [ $id, $v ];
}
$conf->{filters } and $v = $self->$_filter( $conf->{filters }, $id, $v );
$conf->{validate} and $self->$_validate( $conf->{validate}, $id, $v );
return $v;
}
1;
__END__
( run in 0.540 second using v1.01-cache-2.11-cpan-71847e10f99 )