RSS Git Download  Clone
Raw Blame History
package LIMS::Controller::Roles::FormData;

use Moose::Role;
use Data::Dumper;

has results_data_validation => ( is => 'ro', lazy_build => 1 );
sub _build_results_data_validation {
    $_[0]->get_yaml_file('results_data_validation');
}
has test_name_map => ( is => 'ro', lazy_build => 1 ); # don't use name 'lab_tests_map'
sub _build_test_name_map {
    my $aref = $_[0]->model('LabTest')->get_lab_tests; # warn Dumper $aref;
    my %h = map { $_->id => $_->test_name } @$aref; # warn Dumper \%h;
    return \%h;
}
has results_input_errors => (
    is      => 'ro',
    isa     => 'ArrayRef[Str]',
    traits  => ['Array'],
    default => sub { [] },
    handles => {
        all_results_errors  => 'elements',
        have_results_errors => 'count',
        add_results_error   => 'push',
    },
);

use Data::FormValidator;
use LIMS::Local::Config;

sub get_data_from_dfv {
    my $self = shift;
    my $profile = shift
        || return $self->error('no profile passed to get_data_from_dfv()');

	my $validator = $self->_get_validator(); # warn Dumper $validator;

    my $dfv = $validator->check($self->query, $profile);
    my $data = $dfv->valid(); # $self->debug($data);

    return $data;
}

sub validate_form_params {
    my $self = shift;
    my $profile = shift
        || return $self->error('no profile passed to get_data_from_dfv()');
    my $params = shift || $self->query(); # optional - uses CGI if not passed

	my $validator = $self->_get_validator(); # warn Dumper $validator;

    my $results = $validator->check($params, $profile); # warn Dumper $results;
    return $results;
}

sub validate_results_data_entry {
    my ($self, $ref) = @_; # warn Dumper $ref;

    my $test_label = $ref->{test_label};
    my $data_type  = $ref->{data_type};
    my $test_id    = $ref->{test_id};
    my $result     = $ref->{result};

    # form param test name for results passed as lab_test_id_<x>:
    my $form_param_name = 'lab_test_id_' . $test_id;

    # generic validation for data type:
    my $profile_name = 'data_entry_' . $data_type;
    # not all data types need or have validators:
    return 0 unless LIMS::Validate->can($profile_name);
    # get validation method & error msg for profile name:
    my $validator = $self->validate($profile_name); # warn Dumper $validator;

    my $validation_method = $validator->{method};
    my $test_result_pair  = sprintf '%s [%s]', $test_label, $result;

    my $validation_profile = {
        required => [ $form_param_name ], # or param is ignored
        constraint_methods => {
            $form_param_name => $validation_method,
        },
    }; # warn Dumper $validation_profile;
    my $dfv = $self->validate_form_params($validation_profile); # warn Dumper $dfv;
    # add failure msg if invalid:
    if ( $dfv->has_invalid ) {
        my $err_msg = join ': ', $test_result_pair, $validator->{err_msg};
        $self->add_results_error($err_msg);
    }

    # validate against specific format (from yml file) if entry exists, unless
    # already have generic validation failure (has more specific message):
    unless ( $self->have_results_errors ) {
        if ( my $cfg = $self->results_data_validation ) { # warn Dumper $cfg;
            my $test_name = $self->test_name_map->{$test_id}; # warn $test_name;
            my $messages  = $self->messages('dfv_msgs');
            if ( my $regex = $cfg->{$test_name} ) { # warn $regex;
                # warn $result =~ /^$regex$/ ? 'match' : 'no match';
                my $err = $test_result_pair .': '. $messages->{invalid_format};
                $self->add_results_error($err) if $result !~ /^$regex$/;
            }
        }
    }
    my $pass = $self->have_results_errors ? 0 : 1;
    return { pass => $pass }
}

# loads dfv_defaults from LIMS config:
sub _get_validator {
	my $self = shift;

	my $cfg = LIMS::Local::Config->instance;

	my $dfv = Data::FormValidator->new({}, $cfg->{dfv_defaults});
	return $dfv;
}

1;