| File: | blib/lib/Params/Get.pm |
| Coverage: | 93.6% |
| line | stmt | bran | cond | sub | time | code |
|---|---|---|---|---|---|---|
| 1 | package Params::Get; | |||||
| 2 | ||||||
| 3 | 5 5 5 | 258359 4 63 | use strict; | |||
| 4 | 5 5 5 | 7 3 80 | use warnings; | |||
| 5 | ||||||
| 6 | 5 5 5 | 9 4 100 | use Carp; | |||
| 7 | 5 5 5 | 1151 20274 10 | use Devel::Confess; | |||
| 8 | 5 5 5 | 149 5 1405 | use Scalar::Util; | |||
| 9 | ||||||
| 10 | our @ISA = qw(Exporter); | |||||
| 11 | our @EXPORT_OK = qw(get_params); | |||||
| 12 | ||||||
| 13 - 21 | =head1 NAME Params::Get - Get the parameters to a subroutine in any way you want =head1 VERSION Version 0.14 =cut | |||||
| 22 | ||||||
| 23 | our $VERSION = '0.14'; | |||||
| 24 | ||||||
| 25 - 157 | =head1 DESCRIPTION
Exports a single function, C<get_params>, which returns a given value.
When used hand-in-hand with L<Params::Validate::Strict> and L<Return::Set>,
you should be able to formally specify the input and output sets for a method.
=head1 SYNOPSIS
use Params::Get;
use Params::Validate::Strict;
sub where_am_i
{
my $params = Params::Validate::Strict::validate_strict({
args => Params::Get::get_params(undef, \@_),
schema => {
'latitude' => {
type => 'number',
min => -90,
max => 90
}, 'longitude' => {
type => 'number',
min => -180,
max => 180
}
}
});
print 'You are at ', $params->{'latitude'}, ', ', $params->{'longitude'}, "\n";
}
where_am_i(latitude => 0.3, longitude => 124);
where_am_i({ latitude => 3.14, longitude => -155 });
=head1 METHODS
=head2 get_params
Parse the arguments given to a function.
Processes arguments passed to methods and ensures they are in a usable format,
allowing the caller to call the function in any way that they want
e.g. `foo('bar')`, `foo(arg => 'bar')`, `foo({ arg => 'bar' })` all mean the same
when called with
get_params('arg', @_);
or
get_params('arg', \@_);
Some people like this sort of model, which is also supported.
use MyClass;
my $str = 'hello world';
my $obj = MyClass->new($str, { type => 'string' });
package MyClass;
use Params::Get;
sub new {
my $class = shift;
my $rc = Params::Get::get_params('value', \@_);
return bless $rc, $class;
}
=head2 The C<$default> Parameter
The first argument is the C<$default> parameter controls how single-argument calls are interpreted and provides
a default key name for parameter extraction in those cases.
When no arguments are provided with a defined C<$default>:
get_params('required'); # Throws usage error
The function requires either arguments or an undefined C<$default>.
=head3 Usage Examples
=over 2
=item * Simple scalar parameter:
sub set_country {
my $params = get_params('country', @_);
# Accepts: set_country('US')
# Returns: { country => 'US' }
}
=item * Object constructor with options:
sub new {
my $class = shift;
my $params = get_params('value', @_);
# Accepts: MyClass->new($object)
# Accepts: MyClass->new($object, { option => 'value' })
# Returns: { value => $object } or { value => $object, option => 'value' }
}
=item * Hash parameter:
sub configure {
my $params = get_params('config', @_);
# Accepts: configure({ db => 'mysql', host => 'localhost' })
# Returns: { config => { db => 'mysql', host => 'localhost' } }
}
=item * Without default (named parameters only):
sub process {
my $params = get_params(undef, @_);
# Accepts: process(name => 'John', age => 30)
# Returns: { name => 'John', age => 30 }
}
=back
=head3 Caveats
=over 2
=item * When C<$default> is defined and no arguments are provided, an error is thrown
=item * There's no way to specify that a default parameter is optional
=item * Single hash references always bypass the default parameter naming
=back
=cut | |||||
| 158 | ||||||
| 159 | sub get_params | |||||
| 160 | { | |||||
| 161 | # Directly return hash reference if the only parameter is a hash reference | |||||
| 162 | 60 | 388422 | return $_[0] if((scalar(@_) == 1) && (ref($_[0]) eq 'HASH')); # Note - doesn't check if "default" was given | |||
| 163 | ||||||
| 164 | 58 | 43 | my $default = shift; | |||
| 165 | ||||||
| 166 | 58 | 75 | if(ref($default)) { | |||
| 167 | 0 | 0 | Carp::croak(__PACKAGE__, '::get_params: $default must be a scalar'); | |||
| 168 | } | |||||
| 169 | ||||||
| 170 | 58 | 31 | my $args; | |||
| 171 | my $array_ref; | |||||
| 172 | 58 | 92 | if((scalar(@_) == 1) && (ref($_[0]) eq 'ARRAY')) { | |||
| 173 | 21 14 8 3 | 19 21 14 4 | if($default && (scalar(@{$_[0]}) == 2) && (@{$_[0]}[0] eq $default) && (!ref(@{$_[0]}[1]))) { | |||
| 174 | # in main: | |||||
| 175 | # routine('country' => 'US'); | |||||
| 176 | # in routine(): | |||||
| 177 | # $params = Params::Get::get_params('country', \@); | |||||
| 178 | 2 2 | 2 4 | return { $default => @{$_[0]}[1] }; | |||
| 179 | } | |||||
| 180 | 19 | 9 | $args = $_[0]; | |||
| 181 | 19 | 13 | $array_ref = 1; | |||
| 182 | } else { | |||||
| 183 | 37 | 26 | $args = \@_; | |||
| 184 | } | |||||
| 185 | ||||||
| 186 | 56 56 | 34 38 | my $num_args = scalar(@{$args}); | |||
| 187 | ||||||
| 188 | # Populate %rc based on the number and type of arguments | |||||
| 189 | 56 | 44 | if($num_args == 1) { | |||
| 190 | 30 | 28 | if(defined($default)) { | |||
| 191 | 17 | 19 | if(!ref($args->[0])) { | |||
| 192 | # %rc = ($default => shift); | |||||
| 193 | 5 | 16 | return { $default => $args->[0] }; | |||
| 194 | } | |||||
| 195 | 12 | 10 | if(ref($args->[0]) eq 'ARRAY') { | |||
| 196 | 1 | 2 | return { $default => $args->[0] }; | |||
| 197 | } | |||||
| 198 | 11 | 14 | if(ref($args->[0]) eq 'SCALAR') { | |||
| 199 | 3 3 | 3 6 | return { $default => ${$args->[0]} }; | |||
| 200 | } | |||||
| 201 | 8 | 9 | if(ref($args->[0]) eq 'CODE') { | |||
| 202 | 2 | 7 | return { $default => $args->[0] }; | |||
| 203 | } | |||||
| 204 | 6 | 8 | if(Scalar::Util::blessed($args->[0])) { | |||
| 205 | 2 | 7 | return { $default => $args->[0] }; | |||
| 206 | } | |||||
| 207 | } | |||||
| 208 | 17 | 17 | if(!defined($args->[0])) { | |||
| 209 | 1 | 2 | return; | |||
| 210 | } | |||||
| 211 | 16 | 15 | if(ref($args->[0]) eq 'REF') { | |||
| 212 | 1 1 | 3 1 | $args->[0] = ${$args->[0]}; | |||
| 213 | } | |||||
| 214 | 16 | 18 | if(ref($args->[0]) eq 'HASH') { | |||
| 215 | 14 | 23 | return $args->[0]; | |||
| 216 | } | |||||
| 217 | 2 1 | 5 1 | if((ref($args->[0]) eq 'ARRAY') && (scalar(@{$args->[0]}) == 0)) { | |||
| 218 | # in main: | |||||
| 219 | # routine('countries' => []); | |||||
| 220 | # in routine(): | |||||
| 221 | # $params = Params::Get::get_params('countries', \@); | |||||
| 222 | 1 | 1 | if(defined($default)) { | |||
| 223 | 0 | 0 | return { $default => [] } | |||
| 224 | } | |||||
| 225 | 1 | 2 | return $args->[0]; | |||
| 226 | } | |||||
| 227 | 1 | 7 | Carp::croak('Usage: ', __PACKAGE__, '->', (caller(1))[3], '()'); | |||
| 228 | } | |||||
| 229 | 26 | 24 | if($num_args == 0) { | |||
| 230 | 7 | 8 | if(defined($default)) { | |||
| 231 | # if(defined($_[0]) && (ref($_[0]) eq 'ARRAY')) { | |||||
| 232 | # FIXME | |||||
| 233 | # return { $default => [] }; | |||||
| 234 | # } | |||||
| 235 | # FIXME: No means to say that the default is optional | |||||
| 236 | # Carp::croak('Usage: ', __PACKAGE__, '->', (caller(1))[3], "($default => \$val)"); | |||||
| 237 | 4 | 33 | Carp::croak(Devel::Confess::longmess("Usage: ", __PACKAGE__, '->', (caller(1))[3], "($default => \$val)")); | |||
| 238 | } | |||||
| 239 | 3 | 4 | return; | |||
| 240 | } | |||||
| 241 | 19 | 32 | if(($num_args == 2) && (ref($args->[1]) eq 'HASH')) { | |||
| 242 | 5 | 4 | if(defined($default)) { | |||
| 243 | 5 5 | 3 7 | if(scalar keys %{$args->[1]}) { | |||
| 244 | 5 | 5 | if($args->[0] eq $default) { | |||
| 245 | 1 | 2 | return { $default => $args->[1] }; | |||
| 246 | } | |||||
| 247 | # Obj->new('foo', { 'key1' => 'val1' } - set foo to the mandatory first argument, and the rest are options | |||||
| 248 | return { | |||||
| 249 | $default => $args->[0], | |||||
| 250 | 4 4 | 5 10 | %{$args->[1]} | |||
| 251 | }; | |||||
| 252 | } | |||||
| 253 | # Obj->new(foo => {}) - set foo to be an empty hash | |||||
| 254 | 0 | 0 | return { $default => $args->[1] } | |||
| 255 | } | |||||
| 256 | } | |||||
| 257 | ||||||
| 258 | 14 | 15 | if($array_ref && defined($default)) { | |||
| 259 | 4 | 7 | return { $default => $args }; | |||
| 260 | } | |||||
| 261 | 10 | 13 | if(($num_args % 2) == 0) { | |||
| 262 | 10 10 | 6 14 | my %rc = @{$args}; | |||
| 263 | 10 | 20 | return \%rc; | |||
| 264 | } | |||||
| 265 | ||||||
| 266 | 0 | Carp::croak('Usage: ', __PACKAGE__, '->', (caller(1))[3], '()'); | ||||
| 267 | } | |||||
| 268 | ||||||
| 269 - 335 | =head1 AUTHOR Nigel Horne, C<< <njh at nigelhorne.com> >> =head1 BUGS Sometimes giving an array ref rather than array fails. =head1 SEE ALSO =over 4 =item * L<Params::Smart> =item * L<Params::Validate::Strict> =item * L<Return::Set> =item * L<Test Dashboard|https://nigelhorne.github.io/Params-Get/coverage/> =back =head1 SUPPORT This module is provided as-is without any warranty. Please report any bugs or feature requests to C<bug-params-get at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Params-Get>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. You can find documentation for this module with the perldoc command. perldoc Params::Get You can also look for information at: =over 4 =item * MetaCPAN L<https://metacpan.org/dist/Params-Get> =item * RT: CPAN's request tracker L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Params-Get> =item * CPAN Testers' Matrix L<http://matrix.cpantesters.org/?dist=Params-Get> =item * CPAN Testers Dependencies L<http://deps.cpantesters.org/?module=Params::Get> =back =head1 LICENCE AND COPYRIGHT Copyright 2025-2026 Nigel Horne. Usage is subject to the GPL2 licence terms. If you use it, please let me know. =cut | |||||
| 336 | ||||||
| 337 | 1; | |||||