summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2015-09-20 09:33:58 +0200
committerYorhel <git@yorhel.nl>2015-09-20 09:33:58 +0200
commitd53385db68107234e9c06f82387f6251ae9fc2dc (patch)
treeac296acca01546180c7ee3a1880581261c29be5a
parent4223f4a6f345de8df0dd311ee624baee69f8202d (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.pm42
-rw-r--r--t/kv_validate.t27
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 ],