Mojolicious-Plugin-Vparam
view release on metacpan or search on metacpan
lib/Mojolicious/Plugin/Vparam.pm view on Meta::CPAN
=head1 DESCRIPTION
Features:
=over
=item *
Simple syntax or full featured
=item *
Many predefined types
=item *
Shortcuts for the most common uses
=item *
Filters complementary types
=item *
Support arrays and hashes of values
=item *
Support HTML checkbox as bool
=item *
Simple JSON values extraction and validation using JSON Pointer from
L<Mojo::JSON::Pointer>.
=item *
Simple XML/HTML values extraction and validation using CSS selector engine
from L<Mojo::DOM::CSS> or XPath from L<XML::LibXML>.
=item *
Support objects via parameters
=item *
Validate all parameters at once and get hash to simple use in any Model
=item *
Manage validation errors
=item *
Full Mojolicious::Validator::Validation integration
=back
This module use simple parameters types B<str>, B<int>, B<email>, B<bool>,
etc. to validate.
Instead of many other modules you mostly not need add specific validation
subs or rules.
Just set parameter type. But if you want sub or regexp you can do it too.
=head1 SYNOPSIS
# Add plugin in startup
$self->plugin('Vparam');
# Use in controller
$login = $self->vparam(login => 'str');
$passw = $self->vparam(password => 'password', size => [8, 100]);
$email = $self->vparam(email => 'email', optional => 1);
$session = $self->vparam(session => 'bool', default => 1);
$ids = $self->vparam(ids => '@int');
=head1 METHODS
=head2 vparam
Get one parameter. By default parameter is required.
# Simple get one parameter
$param1 = $self->vparam(date => 'datetime');
# Or more syntax
$param2 = $self->vparam(count => {type => 'int', default => 1});
# Or more simple syntax
$param2 = $self->vparam(count => 'int', default => 1);
=head2 vparams
Get many parameters as hash. By default all parameters are required.
%params = $self->vparams(
# Simple syntax
name => 'str',
password => qr{^\w{8,32}$},
myparam => sub { $_[1] && $_[1] eq 'ok' ? 1 : 0 } },
someone => ['one', 'two', 'tree'],
# More syntax
from => { type => 'date', default => '' },
to => { type => 'date', default => '' },
id => { type => 'int' },
money => { regexp => qr{^\d+(?:\.\d{2})?$} },
myparam => { post => sub { $_[1] && $_[1] eq 'ok' ? 1 : 0 } },
# Checkbox
isa => { type => 'bool', default => 0 },
);
=head2 vsort
Like I<vparams> but add some keys to simple use with tables. Example:
# HTML - table with controls and filters
Order by:
<select name="oby">
lib/Mojolicious/Plugin/Vparam.pm view on Meta::CPAN
Value of B<oby> The value will be automatically mapped to the column name
using the L</-sort> attribute.
Also, the value will be checked for proper mapping.
So you do not need to worry about it.
=item ods
Sort order ASC|DESC. Default: ASC.
You can set different name by I<vsort_ods> config parameter.
If you set undef then parameter is not apply.
=back
=head2 verror $name
Get parameter error string. Return 0 if no error.
# Get error
print $self->verror('myparam');
# Get error for first element in array
print $self->verror('myparam' => 0);
# Set error
$self->verror('myparam', message => 'Error message')
=head2 verrors
Return errors count in scalar context. In list context return errors hash.
# List context get hash
my %errors = $self->verrors;
# Scalar context get count
die 'Errors!' if $self->verrors;
=head2 vclass $name, @classes
Get classes for invalid input. Return empty string if no error.
# Form example
<input name="myparam" class="<%= vclass 'myparam' %>">
# Return next code for invalid I<myparam>:
# <input name="myparam" class="field-with-error">
You can set additional I<@classes> to set if field invalid.
=head2 vvalue $name, $default
Get raw input value after validation. Return I<$default> value or empty
string before validation.
# Form example:
<input name="myparam" value="<%= vvalue 'myparam' %>">
# Return next code if user just open form without submit and validation:
# <input name="myparam" value="">
# Then user submit form and you validate id. For example user submit "abc":
# <input name="myparam" value="abc">
=head2 vtype $name, %opts
Set new type $name if defined %opts. Else return type $name definition.
# Get type
$self->vtype('mytype');
# Set type
# load - requires modules
# pre - get int
# valid - check for not empty
# post - force number
$self->vtype('mytype',
pre => sub {
my ($self, $param) = @_;
return int $param // '';
},
valid => sub {
my ($self, $param) = @_;
return length $param ? 0 : 'Invalid'
},
post => sub {
my ($self, $param) = @_;
return 0 + $param;
}
);
=head2 vfilter $name, &sub
Set new filter $name if defined %opts. Else return filter $name definition.
# Get filter
$self->vfilter('myfilter');
# Set filter
$self->vfilter('myfilter', sub {
my ($self, $param, $expression) = @_;
return $param eq $expression ? 0 : 'Invalid';
});
Filter sub must return 0 if parameter value is valid. Or error string if not.
=head1 SIMPLE SYNTAX
You can use the simplified syntax instead of specifying the type,
simply by using an expression instead.
=over
=item I<REGEXP>
Apply as L</regexp> filter. No type verification, just match.
$self->vparam(myparam => qr{^(abc|cde)$});
=item I<CODE> $mojo, $value
Apply as L</post> function. You need manual verify and set error.
lib/Mojolicious/Plugin/Vparam.pm view on Meta::CPAN
=head2 lon
Longitude.
=head2 lat
Latilude.
=head2 isin
International Securities Identification Number:
Mir, American Express, Diners Club, JCB, Visa,
MasterCard, Maestro, etc.
You can check for ISIN type like:
# Mir
$self->vparam(card => 'isin', regexp => qr{^2});
# American Express, Diners Club, JCB
$self->vparam(card => 'isin', regexp => qr{^3});
# Visa
$self->vparam(card => 'isin', regexp => qr{^4});
# MasterCard
$self->vparam(card => 'isin', regexp => qr{^5});
# Maestro
$self->vparam(card => 'isin', regexp => qr{^6});
=head2 maestro
Some local country, not 16 numbers cards: Maestro, Visa Electron, etc.
=head3 creditcard
Aggregate any creditcard: ISIN, Maestro, etc.
=head2 barcode
Barcode: EAN-13, EAN-8, EAN 5, EAN 2, UPC-12, ITF-14, JAN, UPC, etc.
$self->vparam(barcode => 'goods');
=head2 inn
RU: Taxpayer Identification Number
=head2 kpp
RU: Code of reason for registration
=head2 object
Simple objects via parameters (without validation!). Example:
# {foo => [ {bar => 1, baz => 2} ]}
?param1[foo][0][bar]=1¶m1[foo][0][baz]=2
This is experimental feature. We think how to validate parameters.
=head1 ATTRIBUTES
You can set a simple mode as in example or full mode. Full mode keys:
=head2 default
Default value. Default: undef.
# Supress myparam to be undefined and error
$self->vparam(myparam => 'str', default => '');
=head2 load
Autoload module for this type.
Can be module name, array of module names or sub.
=head2 pre $mojo, &sub
Incoming filter sub. Used for primary filtration: string length and trim, etc.
Result will be used as new param value.
Usually, if you need this attribute, you need to create a new type.
=head2 valid $mojo, &sub
Validation sub. Return 0 if valid, else string of error.
Usually, if you need this attribute, you need to create a new type.
=head2 post $mojo, &sub
Out filter sub. Used to modify value for use in you program. Usually used to
bless in some object.
Result will be used as new param value.
=head2 type
Parameter type. If set then some filters will be apply. See L</TYPES>.
$self->vparam(myparam => 'datetime');
$self->vparam(myparam => {type => 'datetime'});
$self->vparams(
myparam1 => {type => 'datetime'},
myparam2 => {isa => 'datetime'},
);
After the application of the type used filters.
You can use B<isa> alias instead of B<type>.
=head2 as
Rename output key for I<vparams> to simple use in models.
# Return {login => '...', password => '...'}
$self->vparams(
myparam1 => {type => 'str', as => 'login'},
myparam2 => {type => 'str', as => 'password'},
lib/Mojolicious/Plugin/Vparam.pm view on Meta::CPAN
# Simple vparam
# myparam is undef.
$param1 = $self->vparam(param1 => 'int', optional => 1, skipundef => 1);
# Simple flag
# The %params hash is empty if myparam value is not integer.
%params = $self->vparams(
myparam => { type => 'int', optional => 1, skipundef => 1 },
);
# Set all in vparams
# The %params hash is empty if all parameters are not valid.
%params = $self->vparams(
-skipundef => 1,
param1 => 'int',
param2 => 'str',
);
# Shortcut syntax: skipundef and optional is on
$param2 = $self->vparam(param2 => '~int');
Arrays always return as arrayref. But undefined values will be skipped:
# This vparam return [1,2,3] for ?param3=1¶m3=¶m3=2¶m3=3
$param2 = $self->vparam(param3 => '~int');
=head2 multiline
You can simple split I<textarea> to values:
# This vparam return [1,2,3] for input "1\n2\n3\n"
$param1 = $self->vparam(param1 => 'int', multiline => 1);
# Or by custom regexp
# This vparam return [1,2,3] for input "1,2,3"
$param1 = $self->vparam(param1 => 'int', multiline => qr{\s*,\s*});
Empty lines ignored.
=head2 multijoin
Any array values can be joined in string:
# This vparam return "1,2,3" for input ?param1=1¶m1=2¶m1=3
$param1 = $self->vparam(param1 => 'int', multijoin => ',');
# This vparam return "1,2,3" for input "1\n2\n3\n"
$param2 = $self->vparam(param2 => 'int', multiline => 1, multijoin => ',');
=head2 blessed
Keep and return blessed object for parsed parameters if available.
Vparam always return scalars if disabled.
Note: if defined I<date>, I<time>, I<datetime> then always return
formatted scalar.
=head2 jpath or jpath?
If you POST data not form but raw JSON you can use JSON Pointer selectors
from L<Mojo::JSON::Pointer> to get and validate parameters.
# POST data contains:
# {"point":{"address":"some", "lon": 45.123456, "lat": 38.23452}}
%opts = $self->vparams(
address => { type => 'str', jpath => '/point/address' },
lon => { type => 'lon', jpath => '/point/lon' },
lat => { type => 'lat', jpath => '/point/lat' },
);
Note: we don`t support multikey in json. Use hash or die.
If You use C<jpath?> instead C<jpath>, vparam tries parse input json, if
json is invalid vparam tries fetch param from input form:
######################## works:
# {"point":{"address":"some", "lon": 45.123456, "lat": 38.23452}}
# #######################works:
# address=some&lon=45.123456&lat=38.23452
################# doesn't work:
# query: address=some
# body: {"point":{"lon": 45.123456, "lat": 38.23452}}
%opts = $self->vparams(
address => { type => 'str', 'jpath?' => '/point/address' },
lon => { type => 'lon', 'jpath?' => '/point/lon' },
lat => { type => 'lat', 'jpath?' => '/point/lat' },
);
Note: You cant mix C<jpath> and C<jpath?>: If body contains valid JSON, vparam
doesn't try check form params.
=head2 cpath
Same as jpath but parse XML/HTML using CSS selectors from L<Mojo::DOM::CSS>.
# POST data contains:
# <Point>
# <Address>some</Address>
# <Lon>45.123456</Lon>
# <Lat>38.23452</Lat>
# </Point>
%opts = $self->vparams(
address => { type => 'str', cpath => 'Point > Address' },
lon => { type => 'lon', cpath => 'Point > Lon' },
lat => { type => 'lat', cpath => 'Point > Lat' },
);
=head2 xpath
Same as cpath but parse XML/HTML using XPath selectors from L<XML::LibXML>.
# POST data contains:
# <Point time="2016-11-25 14:39:00 +0300">
( run in 1.179 second using v1.01-cache-2.11-cpan-39bf76dae61 )