NAME

Data::Verify - versatile data/type verification, validation and testing

SYNOPSIS

use Data::Verify qw(assess verify);

{
	package Data::Verify::Type;

	our $digit_not_0 = Data::Verify::Type->new(

		desc => 'a number or digit, but not 0',

		extends => [qw(limited)],

		pass => { match => qr/[\d]+/ },

		fail => { match => qr/^0+$/ }

	);

	our $german_zip = Data::Verify::Type->new(

		desc => 'a german zip code',

		extends => [qw(number)],

		pass => { less => 7 },

		fail => { less => 4 }
	);
}

verify( label => 'my personal digit', value => '12', type => 'digit_not_0' );

verify( label => 'an foreign zip', value => '999-233', type => 'german_zip' );

$bouncer->inspect( $user );

DESCRIPTION

A sceptic programmer never trusts anybodys input (web forms, config files, etc.). He verifys if the data is in the right format. With this module he can do it in a very elegant and efficient way. Using object oriented techniques, you can create a hierarchy of tests for verifying almost everything.

The verification procedure is like a simple program. The building blocks are called tests (While this has little to do with modules like Test::Simple, the term 'test' is used because it behaves like it ). Multiple tests result into a 'test program'. While some tests may be expected to fail, and some to pass to result into a valid verification. I call every data which passes the complete program as expected belonging to a 'data type' (So i use this term instead of 'test program').

Here an example in pseudo-code for two data-types:

DATA_TYPE_B
{
	PASS
	{
		TEST_1
		TEST_2
	}
}

DATA_TYPE_A (extends DATA_TYPE_B)
{
	PASS
	{
		TEST_5
		TEST_6
	}

	FAIL
	{
		TEST_1
		TEST_2
		TEST_3
		TEST_4
	}
}

This means: Data is (belonging to) 'DATA_TYPE_A' when it is passing test 5 and 6 with success, and is failing tests 1,2,3 and 4. It also EXTENDS 'DATA_TYPE_B', that means that "DATA_TYPE_A" inherits all "DATA_TYPE A" PASS+FAIL tests.

TESTS

Tests are simply subroutines in the Data::Verify::Test package. Per definition a test receives: 1) the test value 2) the test arguments. Then it simply returns true or false.

Here a very simple example:

sub my_test { $_[0] > $_[1] }	# my_test( 12300, 100 ) would test if 12300 is bigger than 100

PREDEFINED TESTS

Following tests are always instantly available.

range 	- takes two arguments where the value has to be inbetween (ie. range => [1,800] )

lines 	- counts the lines (\n) (ie. lines => 5 )

less 	- lesser than the length in characters (ie. less => 3)

match 	- takes a regex to match (ie. match => qr/^0+$/ )

is 		- exact string comparision (ie. is => 'follow' )

bool 	- transformation of the value into bool (ie. bool => undef)

NULL 	- exact string match 'NULL' (ie. NULL => 1)

exists_in - checks whether the <var> is in a list. if list is an

	Array:	look if exact string is a member

	Hash:	look if the <var> key exists

	Example:

		pass => { exists_in => { firstname => 1, lastname => 1, email => 1 } },

		fail => { exists_in => [qw(blabla)] }

DATA TYPES

A data can be simply instanciated by creation of a new Data::Verify::Type object.

Example (how to create a new data type):

package Data::Verify::Type;

	our $number_notnull = new Data::Verify::Type(

		desc => 'a number or digit, but not 0',

		extends => [qw(number)],

		fail => { match => qr/^0+$/ }
	);

Normally we should have added 'pass => { match => qr/\d+/ },', but we dont explicitly need to add it
because we inherit that from 'number'. Note: A regex-guru would have written simply a better regex which
would had done it with just one match, but this example is for education purposes.

PREDEFINED DATA TYPES

Following types are always instantly available.

true 		- a boolean true value

false		- a boolean false value

not_null	- not the string "NULL"

null		- must be the string "NULL"

limited	- a word longer than 1 character

text		- a standard length text ( 1-800 characters )

word		- a word ( match => qr/[a-zA-Z\-]+[0-9]*/ } )

name		- a first- or lastnames

login     - a login- or nickname

email		- an email address

number	- a number or digit

number_notnull 	- a number or digit, but not 0

zip_ger	- a german zip code

phone_ger - a german phone number

creditcard	- a credit-card number (not implemented yet)

FUNCTIONS

verify( $teststring, $data_type )

Verifies a 'value' against a 'type'.

Example:

my $verify_result = verify( label => 'Config.Author.Level', value => 'NULL', type => 'not_null' );

assess( $verify_result ) # this would fail

Because verify returns a hashref containing information about the test result, you must use 'assess' (below) to transform it to a simple boolean value.

assess( $verify_result )

Use 'assess' to process the result of 'verify' to a simple boolean value.

Example:

assess( verify( value => 0, type => 'false' );	# would return true

describe( Data::Verify )

Prints out an english text, describing how the format has to be and how it is tested.

Bouncer Interface

Observes/Inspects other objects if they fullfil a list of tests.

A bouncer in front of a disco makes decisions. He inspects other persons if they meet the criteria/expectations to be accepted to enter the party or not. The criteria are instructed by the boss. This is also how "Bouncer" works: it inspects other objects and rejects/accepts them.

Shortly i call it 'object bouncing'.

EXAMPLE

use Data::Verify;

my $user = new User( email => 'hiho@test.de', registered => 1 );

my $user_bouncer = Bouncer->new(

	tests =>
	[
		Bouncer::Test->new( field => 'email', type => 'email' ),

		Bouncer::Test->new( field => 'registered', type => 'not_null' ),

		Bouncer::Test->new( field => 'firstname', type => 'word' ),

		Bouncer::Test->new( field => 'lastname', type => 'word' )
	]
);

if( $user_bouncer->inspect( $user ) )
{
	print "User is ok";
}
else
{
	print "rejects User because of unsufficient field:", $@;
}

EXPORT

:all = assess, verify, describe

None by default.

AUTHOR

Murat Uenalan, muenalan@cpan.org

SEE ALSO

Regexp::Common, Data::FormValidator, HTML::FormValidator, CGI::FormMagick::Validator, CGI::Validate, Email::Valid, Email::Valid::Loose, Embperl::Form::Validate