Rex-Dondley-ProcessTaskArgs

 view release on metacpan or  search on metacpan

lib/Rex/Dondley/ProcessTaskArgs.pm  view on Meta::CPAN

our @EXPORT = 'process_task_args';
use Log::Log4perl::Shortcuts qw(:all);

# checks validity of args passed to functions and assigns them to appropriate keys
# Accept 3 sets of args:
# first arg is reference to parameters passed by user to task
# next set of args is a list of allowed params which can also indicate required params
# last arg is an array hash for default values corresponding to each allowed params
sub process_task_args {
  if (!$_[0] || (ref $_[0]) ne 'ARRAY') {
    die 'First argument must be an array ref to user supplied arguments.';
  }

  # standardize the argument data structure
  if (ref $_[0] && ref $_[0]->[0] ne 'HASH') {
    my @args = @{$_[0]};
    shift @_;
    @_ = ([ {}, \@args,], @_ );
  }

  my $passed_in     = shift @_;
  my %passed_params = %{$passed_in->[0]};
  my @unkeyed_args  = @{$passed_in->[1]};
  my @defaults      = ref $_[-1] ? @{$_[-1]} : ();
  pop @_ if @defaults;
  my @valid_args    = @_;
  my @key_list      = grep { $_ && $_ ne '1' && (ref $_) ne 'ARRAY' } @_;

  my %defaults = ();
  my $count = 0;
  foreach my $key (@key_list) {
    $defaults{$key} = $defaults[$count++];
  }

  # create a hash of valid and required keys
  # assumes all values are not required if @valid_args do not contain required value
  my @ordered_keys;
  my %valid_keys = ();
  if ((exists $valid_args[1] && ($valid_args[1] !~ /^0|1$/)) || scalar @valid_args == 1) { # checks to see if list contains required values
    foreach my $arg (@valid_args) {
      $valid_keys{$arg} = 0;
      @ordered_keys = @valid_args;
    }
  } else {
    %valid_keys = @valid_args;
    my $count = 0;
    foreach my $key (@valid_args) {
      if (!($count++ % 2)) {
        push @ordered_keys, $key;
      }
    }
  }

  # check to see if passed parameters are valid
  my @invalid_keys;
  foreach my $key (keys %passed_params) {
    my $is_valid = grep { $_ eq $key } keys %valid_keys;
    if (!$is_valid) {
      push @invalid_keys, $key;
    }
  die ("Invalid key(s): '" . join (', ', @invalid_keys) . "' from ". (caller)[1] . ', line ' . (caller)[2]) if @invalid_keys;
  }


  # Populate the %passed_params hash with @unkeyed_args according
  # to same order they were passed to this function via @valid_args.
  # Throw error if there are more args than available keys.
  if (@unkeyed_args) {
    my @all_array_args = @unkeyed_args;
    foreach my $array_arg (@unkeyed_args) {
      foreach my $vkey (@key_list) {
        if (exists $passed_params{$vkey}) {
          next;
        }
        $passed_params{$vkey} = $array_arg;
        shift @all_array_args;

        last;
      }
    }
    die ('Too many array arguments passed from ' . (caller)[1] . ', line ' . (caller)[2] ) if @all_array_args;

  }

  # Ensure required args are present
  my @reqd_keys     = grep { $valid_keys{$_} } keys %valid_keys;
  my @missing_keys;

  foreach my $rkey(@reqd_keys) {
    if (!exists $passed_params{$rkey} || $passed_params{$rkey} eq '1') {
      push @missing_keys, $rkey unless $defaults{$rkey};
    }
  }
  die ("Missing required key(s): '" . join (', ', @missing_keys) . "' from " . (caller)[1] . ', line ' . (caller)[2]) if @missing_keys;

  # handle edge case when user passes key without value
  foreach my $key (keys %passed_params) {
    if ($passed_params{$key} && $passed_params{$key} eq '1' && $valid_keys{$key}) {
      delete $passed_params{$key};
    }
  }
  my %return_hash = (%defaults, %passed_params);



  if (wantarray) {
    my @blah = @return_hash{ @ordered_keys };
    return @blah;
  } else {
    return \%return_hash;
  }
}
# methods here

1; # Magic true value
# ABSTRACT: easier Rex task argument handling

__END__

=pod

=head1 NAME

Rex::Dondley::ProcessTaskArgs - easier Rex task argument handling

=head1 VERSION

version 0.013

=head1 SYNOPSIS

  use Rex::Dondley::ProcessTaskArgs;

  task 'some_task' => sub {
    # Process args passed to task
    my $params = process_task_args( \@_,                  # arguments passed by user
                                    available_key1 => 1,  # a required argument
                                    available_key2 => 0,  # an optional argument

                                    # optional array hash for default values
                                    [
                                      'default_value_for_key1',
                                      'default_value_for_key2',
                                    ]
                                  );

    # Now retrieve the values as usual
    my $key1 = $params->{key1};
    my $key2 = $params->{key2};
  };

  # If no arguments are required, list of available keys can be simplified:
  task 'another_task' => sub {
    my $params = process_task_args( \@_, key1, key2 [ 'default_value_for_key1' ]);



( run in 0.798 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )