Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
rjbs committed Sep 12, 2008
0 parents commit 9a62374
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 0 deletions.
61 changes: 61 additions & 0 deletions eg/eg.pl
@@ -0,0 +1,61 @@
use strict;
use warnings;

use Data::InputMonster;

sub cgi_param {
my ($form_entry) = @_;
return sub {
my ($monster, $input, $field) = @_;
return $input->req->param->{ $form_entry };
};
}

sub hive_path {
my ($hive_path) = @_;
return sub {
my ($monster, $input, $field) = @_;
return $input->account->info( join q{.}, @$hive_path );
};
}

sub update_hive {
my ($hive_path) = @_;
return sub {
my ($monster, $arg) = @_;

return if $arg->{source} eq 'hive';
return $input->account->info(
(join q{.}, @$hive_path),
$arg->{value};
);
};
}

my $monster = InputMonster->new({
fields => {
per_page => {
check => sub { /\A\d+\z/ && $_ > 0 && $_ < 100 },
store => update_hive([ qw(spam display per_page) ]),
default => 10,
sources => [
per_page => cgi_param('per_page'),
hive => hive_path([ qw(spam display per_page) ]),
],
},
page => {
check => sub { /\A\d+\z/ && $_ > 0 && $_ < 10000 },
default => 1,
sources => [
page => cgi_param('page'),
cur_page => cgi_param('cur_page'),
],
},
search => {
sources => [ cgi_param('search') ],
filter => sub { s/^\s+//; s/\s+$//; },
},
},
});

my $input = $monster->consume($c);
68 changes: 68 additions & 0 deletions lib/Data/InputMonster.pm
@@ -0,0 +1,68 @@
use strict;
use warnings;
package Data::InputMonster;

use Carp ();

sub new {
my ($class, $arg) = @_;

Carp::confess("illegal parameters to Data::InputMonster constructor")
unless $arg and (keys %$arg == 1) and exists $arg->{fields};

my $fields = $arg->{fields};

$class->_assert_field_spec_ok($_) for values %$fields;

bless { fields => $fields } => $class;
}

sub _assert_field_spec_ok {
my ($self, $spec) = @_;

return 1;
}

sub consume {
my ($self, $input) = @_;

my $field = $self->{fields};
my %output;

FIELD: for my $field_name (keys %$field) {
my $spec = $field->{$field_name};

my $checker = $spec->{check};
my $filter = $spec->{filter};
my $storer = $spec->{store};

my @sources = @{ $spec->{sources} };

if (ref $sources[0]) {
my $i = 1;
@sources = map { ("source_" . $i++) => $_ } @sources;
}

SOURCE: for (my $i = 0; $i < @sources; $i += 2) {
my ($name, $getter) = @sources[ $i, $i + 1 ];
my $value = $getter->($self, $input);
next unless defined $value;
if ($filter) { $filter->() for $value; }
if ($checker) { $checker->() or next SOURCE for $value; }

$output{ $field_name } = $value;
if ($storer) {
$storer->($self, { source => $name, value => $value });
}

next FIELD;
}

my $default = $spec->{default};
$output{ $field_name } = ref $default ? $default->() : $default;
}

return \%output;
}

1;
91 changes: 91 additions & 0 deletions t/basic.t
@@ -0,0 +1,91 @@
use strict;
use warnings;

use Test::More 'no_plan';

use Data::InputMonster;

sub stash_a {
my ($entry) = @_;
return sub {
my ($monster, $input, $field) = @_;
return $input->{a}->{ $entry };
};
}

sub stash_b {
my ($entry) = @_;
return sub {
my ($monster, $input, $field) = @_;
return $input->{b}->{ $entry };
};
}

sub update_href {
my ($hash_ref, $field) = @_;
return sub {
my ($monster, $arg) = @_;

$hash_ref->{ $field } = $arg->{value};
};
}

my %stored_data;

sub check_hash {
my ($field) = @_;
sub {
return exists $stored_data{$field} ? $stored_data{$field} : ();
}
}

my $monster = Data::InputMonster->new({
fields => {
per_page => {
check => sub { /\A\d+\z/ && $_ > 0 && $_ < 100 },
store => update_href(\%stored_data, 'per_page'),
default => 10,
sources => [
alpha => stash_a('per_page'),
bravo => stash_b('per_page'),
hash => check_hash('per_page'),
],
},
page => {
check => sub { /\A\d+\z/ && $_ > 0 && $_ < 10000 },
default => 1,
sources => [
alpha_p => stash_a('page'),
alpha_cp => stash_b('cur_page'),
],
},
search => {
sources => [ stash_b('search') ],
check => sub { /\A\w+\z/ },
filter => sub { s/^\s+//; s/\s+$//; },
},
},
});

{
my $input = {
a => { cur_page => 19, per_page => -1, },
b => { per_page => 99, search => " trim_me " },
};

my $result = $monster->consume($input);

is_deeply(
$result,
{
page => 1,
per_page => 99,
search => "trim_me",
},
);

is_deeply(
\%stored_data,
{ per_page => 99, },
);
}

0 comments on commit 9a62374

Please sign in to comment.