package FormValidator::Simple::Validator; use strict; use base qw/Class::Data::Inheritable/; use FormValidator::Simple::Constants; use FormValidator::Simple::Exception; use Email::Valid; use Email::Valid::Loose; use Date::Calc; use UNIVERSAL::require; __PACKAGE__->mk_classdata( options => { } ); sub SP { my ($self, $params, $args) = @_; my $data = $params->[0]; return $data =~ /\s/ ? TRUE : FALSE; } *SPACE = \&SP; sub INT { my ($self, $params, $args) = @_; my $data = $params->[0]; return $data =~ /^\-?[\d]+$/ ? TRUE : FALSE; } sub ASCII { my ($self, $params, $args) = @_; my $data = $params->[0]; return $data =~ /^[\x21-\x7E]+$/ ? TRUE : FALSE; } sub DUPLICATION { my ($self, $params, $args) = @_; my $data1 = $params->[0]; my $data2 = $params->[1]; unless (defined $data1 && defined $data2) { FormValidator::Simple::Exception->throw( qq/validation "DUPLICATION" needs two keys of data./ ); } return $data1 eq $data2 ? TRUE : FALSE; } sub LENGTH { my ($self, $params, $args) = @_; unless ( scalar(@$args) > 0 ) { FormValidator::Simple::Exception->throw( qq/validation "LENGTH" needs one or two arguments./ ); } my $data = $params->[0]; my $length = length $data; my $min = $args->[0]; my $max = $args->[1] || $min; $min += 0; $max += 0; return $min <= $length && $length <= $max ? TRUE : FALSE; } sub REGEX { my ($self, $params, $args) = @_; my $data = $params->[0]; my $regex = $args->[0]; return $data =~ /$regex/ ? TRUE : FALSE; } sub EMAIL { my ($self, $params, $args) = @_; my $data = $params->[0]; return FALSE unless $data; return Email::Valid->address(-address => $data) ? TRUE : FALSE; } sub EMAIL_MX { my ($self, $params, $args) = @_; my $data = $params->[0]; return FALSE unless $data; return Email::Valid->address(-address => $data, -mxcheck => 1) ? TRUE : FALSE; } sub EMAIL_LOOSE { my ($self, $params, $args) = @_; my $data = $params->[0]; return FALSE unless $data; return Email::Valid::Loose->address($data) ? TRUE : FALSE; } sub EMAIL_LOOSE_MX { my ($self, $params, $args) = @_; my $data = $params->[0]; return FALSE unless $data; return Email::Valid::Loose->address(-address => $data, -mxcheck => 1) ? TRUE : FALSE; } sub DATE { my ($self, $params, $args) = @_; my ($year, $month, $day ) = @$params; my $result = Date::Calc::check_date($year, $month, $day) ? TRUE : FALSE; my $data; if ($result) { my $class = $self->options->{datetime_class} || ''; if ($class eq 'DateTime') { $class->require; if ($@) { FormValidator::Simple::Exception->throw( qq/Validation DATE: failed to require $class. "$@"./ ); } my %date = ( year => $year, month => $month, day => $day, ); if ($self->options->{time_zone}) { $date{time_zone} = $self->options->{time_zone}; } $data = $class->new(%date); } elsif ($class eq 'Time::Piece') { $data = sprintf "%04d-%02d-%02d 00:00:00", $year, $month, $day; $class->require; if ($@) { FormValidator::Simple::Exception->throw( qq/Validation DATE: failed to require $class. "$@"./ ); } $data = $class->strptime($data, "%Y-%m-%d %H:%M:%S"); } else { $data = sprintf "%04d-%02d-%02d 00:00:00", $year, $month, $day; } } return ($result, $data); } sub TIME { my ($self, $params, $args) = @_; my ($hour, $min, $sec ) = @$params; $hour ||= 0; $min ||= 0; $sec ||= 0; my $result = Date::Calc::check_time($hour, $min, $sec) ? TRUE : FALSE; my $time = $result ? sprintf("%02d:%02d:%02d", $hour, $min, $sec) : undef; return ($result, $time); } sub DATETIME { my ($self, $params, $args) = @_; my ($year, $month, $day, $hour, $min, $sec) = @$params; $hour ||= 0; $min ||= 0; $sec ||= 0; my $result = Date::Calc::check_date($year, $month, $day) && Date::Calc::check_time($hour, $min, $sec) ? TRUE : FALSE; my $data; if ($result) { my $class = $self->options->{datetime_class} || ''; if ($class eq 'DateTime') { $class->require; if ($@) { FormValidator::Simple::Exception->throw( qq/Validation DATETIME: failed to require $class. "$@"./ ); } my %date = ( year => $year, month => $month, day => $day, hour => $hour, minute => $min, second => $sec, ); if ($self->options->{time_zone}) { $date{time_zone} = $self->options->{time_zone}; } $data = $class->new(%date); } elsif ($class eq 'Time::Piece') { $data = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $hour, $min, $sec; $class->require; if ($@) { FormValidator::Simple::Exception->throw( qq/Validation DATETIME: failed to require $class. "$@"./ ); } $data = $class->strptime($data, "%Y-%m-%d %H:%M:%S"); } else { $data = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $hour, $min, $sec; } } return ($result, $data); } sub ANY { my ($self, $params, $args) = @_; foreach my $param ( @$params ) { return TRUE if ( defined $param && $param ne '' ); } return FALSE; } sub HTTP_URL { my ($self, $params, $args) = @_; my $data = $params->[0]; return $data =~ /^s?https?:\/\/[-_.!~*'()a-zA-Z0-9;\/?:\@&=+\$,%#]+$/ ? TRUE : FALSE; } sub SELECTED_AT_LEAST { my ($self, $params, $args) = @_; my $data = $params->[0]; my $selected = ref $data ? $data : [$data]; my $num = $args->[0] + 0; return scalar(@$selected) >= $num ? TRUE : FALSE; } sub GREATER_THAN { my ($self, $params, $args) = @_; my $data = $params->[0]; my $target = $args->[0]; unless ( $target && $target =~ /^\d+$/ ) { FormValidator::Simple::Exception->throw( qq/Validation GREATER_THAN needs a numeric argument./ ); } return FALSE unless $data =~ /^\d+$/; return ( $data > $target ) ? TRUE : FALSE; } sub LESS_THAN { my ($self, $params, $args) = @_; my $data = $params->[0]; my $target = $args->[0]; unless ( $target && $target =~ /^\d+$/ ) { FormValidator::Simple::Exception->throw( qq/Validation LESS_THAN needs a numeric argument./ ); } return FALSE unless $data =~ /^\d+$/; return ( $data < $target ) ? TRUE : FALSE; } sub EQUAL_TO { my ($self, $params, $args) = @_; my $data = $params->[0]; my $target = $args->[0]; unless ( $target && $target =~ /^\d+$/ ) { FormValidator::Simple::Exception->throw( qq/Validation EQUAL_TO needs a numeric argument./ ); } return FALSE unless $data =~ /^\d+$/; return ( $data == $target ) ? TRUE : FALSE; } sub BETWEEN { my ($self, $params, $args) = @_; my $data = $params->[0]; my $start = $args->[0]; my $end = $args->[1]; unless ( $start && $start =~ /^\d+$/ && $end && $end =~ /^\d+$/ ) { FormValidator::Simple::Exception->throw( qq/Validation BETWEEN needs two numeric arguments./ ); } return FALSE unless $data =~ /^\d+$/; return ( $data >= $start && $data <= $end ) ? TRUE : FALSE; } sub DECIMAL { my ($self, $params, $args) = @_; my $data = $params->[0]; unless ( scalar(@$args) > 0 ) { FormValidator::Simple::Exception->throw( qq/Validation DECIMAL needs one or two numeric arguments./ ); } my $digit1 = $args->[0]; my $digit2 = $args->[1] || 0; unless ( $digit1 =~ /^\d+$/ && $digit2 =~ /^\d+$/ ) { FormValidator::Simple::Exception->throw( qq/Validation DECIMAL needs one or two numeric arguments./ ); } return FALSE unless $data =~ /^\d+(\.\d+)?$/; my $reg = qr/^\d{1,$digit1}(\.\d{0,$digit2})?$/; return $data =~ /$reg/ ? TRUE : FALSE; } 1; __END__