diff options
author | Yorhel <git@yorhel.nl> | 2015-09-20 09:33:58 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2015-09-20 09:33:58 +0200 |
commit | d53385db68107234e9c06f82387f6251ae9fc2dc (patch) | |
tree | ac296acca01546180c7ee3a1880581261c29be5a | |
parent | 4223f4a6f345de8df0dd311ee624baee69f8202d (diff) |
kv_validate(): Allow templates to set more fields
The documentation has always implied that fields like required, default,
rmwhitespace, multi, mincount and maxcount could be set in a template,
but that was never supported. Now it does what you expect it to do.
-rw-r--r-- | lib/TUWF/Misc.pm | 42 | ||||
-rw-r--r-- | t/kv_validate.t | 27 |
2 files changed, 61 insertions, 8 deletions
diff --git a/lib/TUWF/Misc.pm b/lib/TUWF/Misc.pm index 3230d3c..5ab0352 100644 --- a/lib/TUWF/Misc.pm +++ b/lib/TUWF/Misc.pm @@ -59,14 +59,18 @@ sub kv_validate { my %ret; for my $f (@$params) { + # Inherit some options from templates. + !exists($f->{$_}) && _val_from_tpl($f, $_, $templates, $f) + for(qw|required default rmwhitespace multi mincount maxcount|); + my $src = (grep $f->{$_}, keys %$sources)[0]; my @values = $sources->{$src}->($f->{$src}); @values = ($values[0]) if !$f->{multi}; # check each value and add it to %ret for (@values) { - my $errfield = _validate($_, $templates, $f); - next if !$errfield; + my $errfield = _validate_early($_, $f) || _validate($_, $templates, $f); + next if !$errfield || $errfield eq 'default'; push @err, [ $f->{$src}, $errfield, $f->{$errfield} ]; last; } @@ -82,12 +86,24 @@ sub kv_validate { } -# Internal function used by kv_validate, checks one value on the validation -# rules, the name of the failed rule on error, undef otherwise -sub _validate { # value, \%templates, \%rules - my($v, $t, $r) = @_; +sub _val_from_tpl { + my($top_rules, $field, $tpls, $rules) = @_; + return if !$rules->{template}; + my $tpl = $tpls->{$rules->{template}}; + if(exists $tpl->{$field}) { + $top_rules->{$field} = $tpl->{$field}; + } else { + _val_from_tpl($top_rules, $field, $tpls, $tpl); + } +} + + +# Initial validation of a value. Same as _validate() below, but this one +# validates options that need to be checked only once. (The checks in +# _validate() may run several times when templates are used). +sub _validate_early { # value, \%rules + my($v, $r) = @_; - croak "Template $r->{template} not defined." if $r->{template} && !$t->{$r->{template}}; $r->{required}++ if not exists $r->{required}; $r->{rmwhitespace}++ if not exists $r->{rmwhitespace}; @@ -103,8 +119,18 @@ sub _validate { # value, \%templates, \%rules if(!defined($v) || length($v) < 1) { return 'required' if $r->{required}; $_[0] = $r->{default} if exists $r->{default}; - return undef; + return 'default'; } + return undef; +} + + +# Internal function used by kv_validate, checks one value on the validation +# rules, the name of the failed rule on error, undef otherwise +sub _validate { # value, \%templates, \%rules + my($v, $t, $r) = @_; + + croak "Template $r->{template} not defined." if $r->{template} && !$t->{$r->{template}}; # length return 'minlength' if $r->{minlength} && length $v < $r->{minlength}; diff --git a/t/kv_validate.t b/t/kv_validate.t index 612f423..d04c73f 100644 --- a/t/kv_validate.t +++ b/t/kv_validate.t @@ -163,6 +163,9 @@ BEGIN{@tests=( $templates{hex} = { regex => qr/^[0-9a-f]+$/i }; $templates{crc32} = { template => 'hex', minlength => 8, maxlength => 8 }; $templates{prefix} = { func => sub { $_[0] =~ /^$_[1]{prefix}/ }, inherit => ['prefix'] }; + $templates{bool} = { required => 0, default => 0, func => sub { $_[0] = $_[0]?1:0 } }; + $templates{rawtuple} = { rmwhitespace => 0, template => 'tuple' }; + $templates{tuple} = { multi => 1, mincount => 2, maxcount => 2 }; ()}, { param => 'crc', template => 'hex' }, [ crc => '12345678' ], @@ -188,6 +191,30 @@ BEGIN{@tests=( [ x => 'hullo' ], { x => 'hullo', _err => [[ 'x', 'template', 'prefix' ]] }, + { param => 'issexy', template => 'bool' }, + [], + { issexy => 0 }, + + { param => 'issexy', required => 1, template => 'bool' }, + [], + { issexy => undef, _err => [['issexy', 'required', 1]] }, + + { param => 'issexy', template => 'bool' }, + [ issexy => 'HI IM SEXY!' ], + { issexy => 1 }, + + { param => 'tuple', template => 'rawtuple' }, + [ tuple => ' so much space ', tuple => ' more space ' ], + { tuple => [' so much space ', ' more space ' ]}, + + { param => 'tuple', template => 'rawtuple' }, + [ tuple => 1 ], + { tuple => [1], _err => [['tuple', 'mincount', 2]] }, # This error reporting is confusing + + { param => 'tuple', template => 'rawtuple' }, + [ tuple => 1, tuple => 2, tuple => 3 ], + { tuple => [1,2,3], _err => [['tuple', 'maxcount', 2]] }, # Likewise + # num / int / uint templates { param => 'age', template => 'num' }, [ age => 0 ], |