Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9a62374
Showing
3 changed files
with
220 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, }, | ||
); | ||
} |