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 )