Bugzilla – Attachment 56266 Details for
Bug 17433
Koha::Validator. Validation for the masses!
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 17433 - Koha::Validation. Validation for the masses!
Bug-17433---KohaValidation-Validation-for-the-mass.patch (text/plain), 14.46 KB, created by
Olli-Antti Kivilahti
on 2016-10-12 12:30:15 UTC
(
hide
)
Description:
Bug 17433 - Koha::Validation. Validation for the masses!
Filename:
MIME Type:
Creator:
Olli-Antti Kivilahti
Created:
2016-10-12 12:30:15 UTC
Size:
14.46 KB
patch
obsolete
>From 681714ef46f76a164a41e2ff9027fca757355a5f Mon Sep 17 00:00:00 2001 >From: Olli-Antti Kivilahti <olli-antti.kivilahti@jns.fi> >Date: Wed, 12 Oct 2016 15:29:24 +0300 >Subject: [PATCH] Bug 17433 - Koha::Validation. Validation for the masses! > >Koha::Validation->tries now supports data structure validation and some basic type validations. >--- > Koha/Validation.pm | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++-- > t/Koha/Validation.t | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 393 insertions(+), 6 deletions(-) > create mode 100644 t/Koha/Validation.t > >diff --git a/Koha/Validation.pm b/Koha/Validation.pm >index 261f8d5..7681c8c 100644 >--- a/Koha/Validation.pm >+++ b/Koha/Validation.pm >@@ -21,11 +21,15 @@ use utf8; > use strict; > use warnings; > >-use C4::Context; > use Email::Valid; > >+use C4::Context; >+use C4::Biblio; >+ > use vars qw($VERSION); > >+use Koha::Exception::BadParameter; >+ > =head1 NAME > > Koha::Validation - validates inputs >@@ -76,12 +80,13 @@ returns: 1 if the given phone number is valid, 0 otherwise. > sub validate_phonenumber { > my $phonenumber = shift; > >+ my $validatePhoneNumber = C4::Context->preference("ValidatePhoneNumber"); > # make sure we are allowed to validate phone numbers >- return 1 if C4::Context->preference("ValidatePhoneNumber") eq "OFF"; >+ return 1 if $validatePhoneNumber eq "OFF"; > return 1 if not $phonenumber; > return 0 if $phonenumber =~ /(^(\s))|((\s)$)/; > >- my $regex = get_phonenumber_regex(C4::Context->preference("ValidatePhoneNumber")); >+ my $regex = get_phonenumber_regex($validatePhoneNumber); > return ($phonenumber !~ /$regex/) ? 0:1; > } > >@@ -99,19 +104,33 @@ returns: the regex > =cut > > sub get_phonenumber_regex { >- if (C4::Context->preference("ValidatePhoneNumber") eq "ipn") { >+ my ($validatePhoneNumber) = @_; >+ if ($validatePhoneNumber eq "ipn") { > return qr/^((\+)?[1-9]{1,2})?([-\s\.])?((\(\d{1,4}\))|\d{1,4})(([-\s\.])?[0-9]{1,12}){1,2}$/; > } >- elsif (C4::Context->preference("ValidatePhoneNumber") eq "fin") { >+ elsif ($validatePhoneNumber eq "fin") { > return qr/^((90[0-9]{3})?0|\+358([-\s])?)(?!(100|20(0|2(0|[2-3])|9[8-9])|300|600|700|708|75(00[0-3]|(1|2)\d{2}|30[0-2]|32[0-2]|75[0-2]|98[0-2])))(4|50|10[1-9]|20(1|2(1|[4-9])|[3-9])|29|30[1-9]|71|73|75(00[3-9]|30[3-9]|32[3-9]|53[3-9]|83[3-9])|2|3|5|6|8|9|1[3-9])([-\s])?(\d{1,3}[-\s]?){2,12}\d$/; > } > > return qr/(.*)/; >- } >+} >+ >+my ($f, $sf); >+sub getMARCSubfieldSelectorCache { >+ return $sf; >+} >+sub getMARCFieldSelectorCache { >+ return $f; >+} >+sub getMARCSelectorCache { >+ return {f => $f, sf => $sf}; >+} > > > =head2 use_validator > >+DEPRECATED, use tries() >+ > Validates given input with given validator. > > Koha::Validation::use_validator("phone", 123456789); >@@ -140,4 +159,175 @@ sub use_validator { > return 0; > } > >+=HEAD2 tries >+ >+Same as use_validator except wraps exceptions as Exceptions >+See tests in t/Koha/Validation.t for usage examples. >+ >+ my $ok = Koha::Validation->tries('key', ['koha@example.com', 'this@example.com'], 'email', 'a'); >+ try { >+ Koha::Validation->tries('key', 'kohaexamplecom', 'email'); >+ } catch { >+ print $_->message; >+ }; >+ >+@PARAM1 String, human readable key for the value we are validating >+@PARAM2 Variable, variable to be validated. Can be an array or hash or a scalar >+@PARAM3 String, validator selector, eg. email, phone, marcSubfieldSelector, ... >+@PARAM4 String, the expected nested data types. >+ For example 'aa' is a Array of arrays >+ 'h' is a hash >+ 'ah' is a array of hashes >+@RETURNS 1 if everything validated ok >+@THROWS Koha::Exception::BadParameter typically. See individual validator functions for Exception type specifics >+ >+=cut >+ >+sub tries { >+ my ($package, $key, $val, $validator, $types) = @_; >+ >+ if ($types) { >+ my $t = substr($types,0,1); #Get first char >+ $package->$t($key, $val, $validator, substr($types,1)); #Trim first char from types >+ } >+ else { >+ my $err = __PACKAGE__->$validator($val); >+ Koha::Exception::BadParameter->throw(error => "'$key' '$val' $err") if $err; >+ return 1; >+ } >+ return 1; >+} >+ >+sub a { >+ my ($package, $key, $val, $validator, $types) = @_; >+ Koha::Exception::BadParameter->throw(error => _errmsg($key, $val, 'is not an \'ARRAY\'')) unless (ref($val) eq 'ARRAY'); >+ >+ if ($types) { >+ for (my $i=0 ; $i<@$val ; $i++) { >+ my $v = $val->[$i]; >+ my $t = substr($types,0,1); #Get first char >+ $package->$t($key.'->'.$i, $v, $validator, substr($types,1)); #Trim first char from types >+ } >+ } >+ else { >+ for (my $i=0 ; $i<@$val ; $i++) { >+ my $v = $val->[$i]; >+ $package->tries($key.'->'.$i, $v, $validator, $types); >+ } >+ } >+} >+sub h { >+ my ($package, $key, $val, $validator, $types) = @_; >+ Koha::Exception::BadParameter->throw(error => _errmsg($key, $val, 'is not a \'HASH\'')) unless (ref($val) eq 'HASH'); >+ >+ if ($types) { >+ while(my ($k, $v) = each(%$val)) { >+ my $t = substr($types,0,1); #Get first char >+ $package->$t($key.'->'.$k, $v, $validator, substr($types,1)); #Trim first char from types >+ } >+ } >+ else { >+ while(my ($k, $v) = each(%$val)) { >+ $package->tries($key.'->'.$k, $v, $validator, $types); >+ } >+ } >+} >+sub email { >+ my ($package, $val) = @_; >+ >+ return 'is not a valid \'email\'' if (not defined Email::Valid->address($val)); >+ return undef; >+} >+sub double { >+ my ($package, $val) = @_; >+ >+ return 'is not a valid \'double\'' unless ($val =~ /^\d+\.?\d*$/); >+ return undef; >+} >+sub string { >+ my ($package, $val) = @_; >+ >+ return 'is not a valid \'string\', but undefined' unless(defined($val)); >+ return 'is not a valid \'string\', but zero length' if(length($val) == 0); >+ return 'is not a valid \'string\', but a char' if(length($val) == 1); >+ return undef; >+} >+sub phone { >+ my ($package, $val) = @_; >+ >+ my $regex = get_phonenumber_regex(C4::Context->preference("ValidatePhoneNumber")); >+ return 'is not a valid \'phonenumber\'' if ($val !~ /$regex/); >+ return undef; >+} >+ >+=head2 marcSubfieldSelector >+ >+See marcSelector() >+ >+=cut >+ >+sub marcSubfieldSelector { >+ my ($package, $val) = @_; >+ >+ if ($val =~ /^([0-9.]{3})(\w)$/) { >+ ($f, $sf) = ($1, $2); >+ return undef; >+ } >+ ($f, $sf) = (undef, undef); >+ return 'is not a MARC subfield selector'; >+} >+ >+=head2 marcFieldSelector >+ >+See marcSelector() >+ >+=cut >+ >+sub marcFieldSelector { >+ my ($package, $val) = @_; >+ >+ if ($val =~ /^([0-9.]{3})$/) { >+ ($f, $sf) = ($1, undef); >+ return undef; >+ } >+ ($f, $sf) = (undef, undef); >+ return 'is not a MARC field selector'; >+} >+ >+=head2 marcSelector >+ >+Sets package variables >+$__PACKAGE__::f = MARC field code >+$__PACKAGE__::sf = MARC subfield code >+if a correct MARC selector was found >+for ease of access >+The existing variables are overwritten when a new validation check is done. >+ >+Access them using getMARCSubfieldSelectorCache() and getMARCFieldSelectorCache() >+ >+marcSelector can also deal with any value in KohaToMARCMapping. >+marcSubfieldSelector() and marcFieldSelector() deal with MARC-tags only >+ >+@PARAM1, String, current package >+@PARAM2, String, MARC selector, eg. 856u or 110 >+ >+=cut >+ >+sub marcSelector { >+ my ($package, $val) = @_; >+ >+ if ($val =~ /^([0-9.]{3})(\w*)$/) { >+ ($f, $sf) = ($1, $2); >+ return undef; >+ } >+ ($f, $sf) = C4::Biblio::GetMarcFromKohaField($val, ''); >+ return 'is not a MARC selector' unless ($f && $sf); >+ return undef; >+} >+ >+sub _errmsg { >+ my ($key, $val, $err) = @_; >+ return "\"$key\" => \"$val\" $err"; >+} >+ > 1; >diff --git a/t/Koha/Validation.t b/t/Koha/Validation.t >new file mode 100644 >index 0000000..a1c27f6 >--- /dev/null >+++ b/t/Koha/Validation.t >@@ -0,0 +1,197 @@ >+# Copyright 2016 KohaSuomi >+# >+# This file is part of Koha. >+# >+ >+use Modern::Perl; >+use Test::More; >+ >+use Scalar::Util qw(blessed); >+use Try::Tiny; >+ >+use C4::Biblio; >+use Koha::Validation; >+ >+use t::lib::TestObjects::SystemPreferenceFactory; >+use t::lib::TestObjects::ObjectFactory; >+ >+ >+my $globalContext = {}; >+my $spref = t::lib::TestObjects::SystemPreferenceFactory->createTestGroup([ >+ { >+ preference => 'ValidatePhoneNumber', >+ value => 'fin', >+ }, >+ { >+ preference => 'ValidateEmailAddress', >+ value => 1, >+ }, >+ ], undef, $globalContext); >+ >+subtest "Validate email", \&simpleEmail; >+sub simpleEmail { >+ is(Koha::Validation::use_validator('email', 'koha@example.com'), >+ 1, >+ "Valid email"); >+ is(Koha::Validation::use_validator('email', 'koha@examplecom'), >+ 0, >+ "InValid email"); >+} >+ >+subtest "Validate phone", \&simplePhone; >+sub simplePhone { >+ is(Koha::Validation::use_validator('phone', '+358504497763'), >+ 1, >+ "Valid phone"); >+ is(Koha::Validation::use_validator('phone', '+35504497763'), >+ 0, >+ "InValid phone"); >+} >+ >+subtest "Validate array of something", \&arrayOf; >+sub arrayOf { >+ my @array = ('+358504497763', '0451123123'); >+ is(Koha::Validation->tries('phnbr', \@array, 'phone', 'a' ), >+ 1, >+ "Valid phonenumber array"); >+ >+ push(@array, 'soita heti'); >+ try { >+ is(Koha::Validation->tries('phnbr', \@array, 'phone', 'a' ), >+ 'SHOULD THROW AN EXCEPTION!', >+ "InValid phonenumber array"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "InValid phonenumber array"); >+ >+ is($_->message, >+ "'phnbr->2' 'soita heti' is not a valid 'phonenumber'", >+ "Got a well formatted error message"); >+ }; >+} >+ >+subtest "Validate string", \&simpleString; >+sub simpleString { >+ >+ is(Koha::Validation->tries('key', '+358504497763', 'string'), >+ 1, >+ "Valid string"); >+ >+ try { >+ is(Koha::Validation->tries('key', 'A', 'string'), >+ 'SHOULD THROW AN EXCEPTION!', >+ "Not a string, but a char"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "Not a string, but a char"); >+ >+ is($_->message, >+ "'key' 'A' is not a valid 'string', but a char", >+ "Got a well formatted error message"); >+ }; >+ >+ try { >+ is(Koha::Validation->tries('key', '', 'string'), >+ 'SHOULD THROW AN EXCEPTION!', >+ "Not a string, but a nothing"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "Not a string, but a nothing"); >+ }; >+ >+ is(Koha::Validation->tries('key', 'AB', 'string'), >+ 1, >+ "Valid short String"); >+} >+ >+subtest "Array of Array of doubles", \&nestedArrayDoubles; >+sub nestedArrayDoubles { >+ >+ my @array = ([0.4, 1.2], >+ [4.5, 7.9]); >+ is(Koha::Validation->tries('nay', \@array, 'double', 'aa'), >+ 1, >+ "Valid nested array of doubles"); >+ >+ push(@array, [2, 'lol']); >+ try { >+ is(Koha::Validation->tries('nay', \@array, 'double', 'aa'), >+ 'SHOULD THROW AN EXCEPTION!', >+ "InValid nested array of doubles"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "InValid nested array of doubles"); >+ >+ is($_->message, >+ "'nay->2->1' 'lol' is not a valid 'double'", >+ "Got a well formatted error message"); >+ }; >+} >+ >+subtest "MARC Selectors", \&marcSelectors; >+sub marcSelectors { >+ >+ is(Koha::Validation->tries('mrc', '856', 'marcFieldSelector',), >+ 1, >+ "Valid MARC Field selector"); >+ is(Koha::Validation::getMARCFieldSelectorCache, '856', "Validated MARC Field remembered"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, undef, "Not touched MARC Subfield not defined"); >+ >+ try { >+ is(Koha::Validation->tries('mrc', '85u', 'marcFieldSelector',), >+ 'SHOULD THROW AN EXCEPTION!', >+ "InValid MARC Field selector"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "InValid MARC Field selector"); >+ >+ is($_->message, >+ "'mrc' '85u' is not a MARC field selector", >+ "Got a well formatted error message"); >+ }; >+ is(Koha::Validation::getMARCFieldSelectorCache, undef, "InValidated MARC Field forgot"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, undef, "Not touched MARC Subfield not defined"); >+ >+ is(Koha::Validation->tries('mrc', '110a', 'marcSubfieldSelector',), >+ 1, >+ "Valid MARC Subfield selector"); >+ is(Koha::Validation::getMARCFieldSelectorCache, '110', "Validated MARC Field remembered"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, 'a', "Validated MARC Subfield remembered"); >+ >+ try { >+ is(Koha::Validation->tries('mrc', '110', 'marcSubfieldSelector',), >+ 'SHOULD THROW AN EXCEPTION!', >+ "InValid MARC Subfield selector"); >+ } catch { >+ is(ref($_), 'Koha::Exception::BadParameter', >+ "InValid MARC Subfield selector"); >+ >+ is($_->message, >+ "'mrc' '110' is not a MARC subfield selector", >+ "Got a well formatted error message"); >+ }; >+ is(Koha::Validation::getMARCFieldSelectorCache, undef, "InValidated MARC Field forgot"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, undef, "InValidated MARC Subfield forgot"); >+ >+ is(Koha::Validation->tries('mrc', '110a', 'marcSelector',), >+ 1, >+ "Valid MARC selector"); >+ is(Koha::Validation::getMARCFieldSelectorCache, '110', "Validated MARC Field remembered"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, 'a', "Validated MARC Subfield remembered"); >+ >+ is(Koha::Validation->tries('mrc', '245', 'marcSelector',), >+ 1, >+ "Valid MARC selector"); >+ is(Koha::Validation::getMARCFieldSelectorCache, '245', "Validated MARC Field remembered"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, '', "Not given MARC Subfield forgot"); >+ >+ my ($f, $sf) = C4::Biblio::GetMarcFromKohaField('biblio.title', ''); >+ is(Koha::Validation->tries('mrc', 'biblio.title', 'marcSelector'), >+ 1, >+ "biblio.title is a valid MARC Selector"); >+ is(Koha::Validation::getMARCFieldSelectorCache, $f, "Field from KohaToMarcMapping"); >+ is(Koha::Validation::getMARCSubfieldSelectorCache, $sf, "Subfield from KohaToMarcMapping"); >+} >+ >+t::lib::TestObjects::ObjectFactory->tearDownTestContext($globalContext); >+done_testing(); >-- >1.9.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 17433
: 56266