Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

g4.85 Update Validators: EmptyCell, ValueInList and DuplicateTraits #106

Merged
merged 35 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
89db728
Initial commit: Update EmptyCell validator to use getIndices method
carolyncaron Sep 4, 2024
126c72a
Update configureValidators to use setIndices for EmptyCell
carolyncaron Sep 5, 2024
5352caf
Update ValueInList to use validator traits for configuration
carolyncaron Sep 5, 2024
2a522d1
Fixes breaking tests in testValidatorBaseCheckIndices as it uses Valu…
carolyncaron Sep 5, 2024
3f0b396
Switched checkIndices test to use the fake validator class instead of…
carolyncaron Sep 5, 2024
b81290b
Update DuplicateTraits to use validator traits for configuration
carolyncaron Sep 5, 2024
42df1e4
Merge from 4.x including resolved merge conflicts
carolyncaron Sep 12, 2024
becc21e
Mocked the logger in TraitImportFormTest to not print log messages (f…
carolyncaron Sep 12, 2024
d8120bc
Update annotation block for the 3 validators to list input type and n…
carolyncaron Sep 12, 2024
0010c2c
Split ValidatorFileRowScopeTest into 2 test files, and changed the na…
carolyncaron Sep 13, 2024
0704980
Added a README to the Validators folder in tests to set standards for…
carolyncaron Sep 13, 2024
653968d
Updated return value and tests for DuplicateTraits validator
carolyncaron Sep 18, 2024
af3f2fa
Update formValidate tests to work with the newest return array for Du…
carolyncaron Sep 18, 2024
1c790c8
Updated return value and tests for EmptyCell validator
carolyncaron Sep 18, 2024
7054b21
Updated return value and tests for ValueInList validator
carolyncaron Sep 18, 2024
342b991
Updated the foreach loop that checks for validation failures in the T…
carolyncaron Sep 19, 2024
5495d35
Started updating formValidate in the Trait Importer
carolyncaron Sep 19, 2024
1f313c6
Updated validator tests to use AssertSame instead of AssertEquals whe…
carolyncaron Sep 20, 2024
e87faab
Updated Duplicate Trait validator tests to check for all return value…
carolyncaron Sep 20, 2024
aba8edc
Created the processValidationMessages method
carolyncaron Sep 20, 2024
4046823
Updated the Traits Importer to stop using the array and start using …
carolyncaron Sep 20, 2024
819c3e0
Fixed breaking tests in formValidate
carolyncaron Sep 21, 2024
b71e79c
General cleanup of formValidate() and processValidationMessages()
carolyncaron Sep 23, 2024
3e5035b
General cleanup and added documentation to testTraitFormValidation()
carolyncaron Sep 23, 2024
fe9a96c
Apply Lacey's suggestions to documentation/comments
carolyncaron Sep 25, 2024
0abf07f
Addressed Lacey's suggestion to add raw_results inside the messages a…
carolyncaron Sep 25, 2024
3e4dd8a
Merge branch 'g4.85-updateTraitDataValidators' of https://github.com/…
carolyncaron Sep 25, 2024
e016c1b
Merge branch '4.x' into g4.85-updateTraitDataValidators
laceysanderson Sep 26, 2024
630e3db
Update the GenusConfigured trait to set the genus of the trait servic…
laceysanderson Sep 26, 2024
a848d43
Merge branch 'g4.85-updateTraitDataValidators' of https://github.com/…
laceysanderson Sep 26, 2024
5b57cce
Update configuregenus badly config test to use a data provider and in…
laceysanderson Sep 26, 2024
5b4e637
Update genus configured trait test to include the traits service.
laceysanderson Sep 26, 2024
0718ee4
Updated/added exception documentation to GenusConfigured trait and Du…
carolyncaron Sep 27, 2024
b65a321
Moved the single test for a wrong index key given to DuplicateTraits …
carolyncaron Sep 27, 2024
e688f14
Clarified documentation for the new testIndexKeyExceptions test and i…
carolyncaron Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

152 changes: 103 additions & 49 deletions trpcultivate_phenotypes/src/Plugin/Validators/DuplicateTraits.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,36 @@
namespace Drupal\trpcultivate_phenotypes\Plugin\Validators;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\trpcultivate_phenotypes\Service\TripalCultivatePhenotypesTraitsService;
use Drupal\trpcultivate_phenotypes\TripalCultivateValidator\TripalCultivatePhenotypesValidatorBase;
use Drupal\trpcultivate_phenotypes\TripalCultivateValidator\ValidatorTraits\ColumnIndices;
use Drupal\trpcultivate_phenotypes\TripalCultivateValidator\ValidatorTraits\GenusConfigured;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\trpcultivate_phenotypes\Service\TripalCultivatePhenotypesGenusOntologyService;
use Drupal\tripal_chado\Database\ChadoConnection;
use Drupal\trpcultivate_phenotypes\Service\TripalCultivatePhenotypesTraitsService;

/**
* Validate duplicate traits within a file
*
* @TripalCultivatePhenotypesValidator(
* id = "duplicate_traits",
* validator_name = @Translation("Duplicate Traits Validator"),
* validator_scope = "FILE ROW",
* input_types = {"data-row"},
* )
*/
class DuplicateTraits extends TripalCultivatePhenotypesValidatorBase implements ContainerFactoryPluginInterface {

/**
* An associative array containing the needed context, which is dependant
* on the validator. For example, instead of validating each cell by default,
* a validator may need a list of indices which correspond to the columns in
* the row for which the validator should act on.
*
* This validator requires the following keys:
* - genus => a string of the genus name
* - indices => an associative array with the following keys, which are
* column headers of required columns for the Traits Importer:
* This validator requires the following validator traits:
* - GenusConfigured: Gets a string of the configured genus name
* - ColumnIndices => Gets an associative array with the following keys,
* which are column headers of required columns for the Traits Importer:
* - 'Trait Name': int, the index of the trait name column in $row_values
* - 'Method Short Name': int, the index of the method name column in $row_values
* - 'Unit': int, the index of the unit column in $row_values
*/
public array $context = [];
use ColumnIndices;
use GenusConfigured;

/**
* A nested array of already validated values forming the unique trait name +
Expand All @@ -52,18 +52,40 @@ class DuplicateTraits extends TripalCultivatePhenotypesValidatorBase implements
*/
protected $unique_traits = [];

/**
* An instance of the Genus Ontology service for use in the methods in this
* trait.
*
* Services should be injected via depenency injection in your validator class
* and then assigned to this variable in your constructor.
*
* @var TripalCultivatePhenotypesGenusOntologyService
*/
protected TripalCultivatePhenotypesGenusOntologyService $service_PhenoGenusOntology;

/**
* A Database query interface for querying Chado using Tripal DBX.
*
* @var ChadoConnection
*/
protected ChadoConnection $chado_connection;

/**
* Traits Service
*
* @var TripalCultivatePhenotypesTraitsService
*/
protected $service_traits;
protected TripalCultivatePhenotypesTraitsService $service_PhenoTraits;

/**
* Constructor.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, TripalCultivatePhenotypesTraitsService $service_traits) {
public function __construct(array $configuration, $plugin_id, $plugin_definition, ChadoConnection $chado_connection, TripalCultivatePhenotypesGenusOntologyService $service_PhenoGenusOntology, TripalCultivatePhenotypesTraitsService $service_traits) {
parent::__construct($configuration, $plugin_id, $plugin_definition);

$this->service_traits = $service_traits;
$this->chado_connection = $chado_connection;
$this->service_PhenoGenusOntology = $service_PhenoGenusOntology;
$this->service_PhenoTraits = $service_traits;
}

/**
Expand All @@ -74,6 +96,8 @@ public static function create(ContainerInterface $container, array $configuratio
$configuration,
$plugin_id,
$plugin_definition,
$container->get('tripal_chado.database'),
$container->get('trpcultivate_phenotypes.genus_ontology'),
$container->get('trpcultivate_phenotypes.traits')
);
}
Expand All @@ -86,40 +110,52 @@ public static function create(ContainerInterface $container, array $configuratio
* stored as an array element.
*
* @return array
* An associative array with the following keys:
* - title: string, section or title of the validation as it appears in the result window.
* - status: string, pass if it passed the validation check/test, fail string otherwise and todo string if validation was not applied.
* - details: details about the offending field/value.
* An associative array with the following keys.
* - case: a developer focused string describing the case checked.
* - valid: TRUE if the trait is unique and FALSE if it already exists.
* - failedItems: an array of "items" that failed with the following keys, to
* be used in the message to the user. This is an empty array if the data row input was valid.
* - combo_provided: The combo of trait, method, and unit provided in the file.
* The keys used are the same name of the column header for the cell containing
* the desired value.
* - Trait Name: The trait name provided in the file
* - Method Short Name: The method name provided in the file
* - Unit: The unit provided in the file
*/
public function validateRow($row_values) {

// Set our context which was configured for this validator
$context = $this->context;
// Grab our indices
$indices = $this->getIndices();

// Check the indices provided are valid in the context of the row.
// Will throw an exception if there's a problem.
// Typically checkIndices() doesn't take an associative array but
// because it checks the values not the keys, it will work in this
// case as well.
$this->checkIndices($row_values, $context['indices']);
$this->checkIndices($row_values, $indices);

// These are the key names we expect in our indices array
$trait_key = 'Trait Name';
$method_key = 'Method Short Name';
$unit_key = 'Unit';

// Grab our trait, method and unit values from the $row_values array
// using the indices stored in our $context array
// We need to ensure that each array key we expect in $context['indices']
// using our configured $indices array
// We need to ensure that each array key we expect in $indices
// exists, otherwise throw an exception
if (!isset($context['indices']['Trait Name'])) {
throw new \Exception(t('The trait name (key: Trait Name) was not set in the $context[\'indices\'] array'));
if (!isset($indices[$trait_key])) {
throw new \Exception('The trait name (key: Trait Name) was not set by setIndices()');
}
if (!isset($context['indices']['Method Short Name'])) {
throw new \Exception(t('The method name (key: Method Short Name) was not set in the $context[\'indices\'] array'));
if (!isset($indices[$method_key])) {
throw new \Exception('The method name (key: Method Short Name) was not set by setIndices()');
}
if (!isset($context['indices']['Unit'])) {
throw new \Exception(t('The unit (key: Unit) was not set in the $context[\'indices\'] array'));
if (!isset($indices[$unit_key])) {
throw new \Exception('The unit (key: Unit) was not set by setIndices()');
}

$trait = $row_values[$context['indices']['Trait Name']];
$method = $row_values[$context['indices']['Method Short Name']];
$unit = $row_values[$context['indices']['Unit']];
$trait = $row_values[$indices[$trait_key]];
$method = $row_values[$indices[$method_key]];
$unit = $row_values[$indices[$unit_key]];

// Set our flags for tracking database and input file duplicates
$duplicate_in_file = FALSE;
Expand All @@ -135,10 +171,10 @@ public function validateRow($row_values) {
}

// Check if our trait combo exists at the database level
// First make sure to set our genus before getting our trait combo
$this->service_traits->setTraitGenus($context['genus']);
// Grab our traits service
$trait_combo = $this->service_traits->getTraitMethodUnitCombo($trait, $method, $unit);
// NOTE: The trait service was configured to use this genus by
// the GenusConfigured trait when the genus was set.
// Grab our trait combo.
$trait_combo = $this->service_PhenoTraits->getTraitMethodUnitCombo($trait, $method, $unit);
if (!empty($trait_combo)) {
// Duplicate found
$duplicate_in_db = TRUE;
Expand All @@ -152,32 +188,50 @@ public function validateRow($row_values) {
if ($duplicate_in_db) {
// This row is a duplicate of another row AND in the database
$validator_status = [
'title' => 'Duplicate trait combo in file + database',
'status' => 'fail',
'details' => 'A duplicate trait was found within both the input file and the database.'
'case' => 'A duplicate trait was found within both the input file and the database',
'valid' => FALSE,
'failedItems' => [
'combo_provided' => [
$trait_key => $trait,
$method_key => $method,
$unit_key => $unit
]
]
];
}
else {
$validator_status = [
'title' => 'Duplicate Trait Name + Method Short Name + Unit combination',
'status' => 'fail',
'details' => 'A duplicate trait was found within the input file'
'case' => 'A duplicate trait was found within the input file',
'valid' => FALSE,
'failedItems' => [
'combo_provided' => [
$trait_key => $trait,
$method_key => $method,
$unit_key => $unit
]
]
];
}
}
else if ($duplicate_in_db) {
$validator_status = [
'title' => 'Duplicate Trait Name + Method Short Name + Unit combination',
'status' => 'fail',
'details' => 'The combination of ' . $trait . ', ' . $method . ', and ' . $unit . ' is already found in the database.'
'case' => 'A duplicate trait was found in the database',
'valid' => FALSE,
'failedItems' => [
'combo_provided' => [
$trait_key => $trait,
$method_key => $method,
$unit_key => $unit
]
]
];
}
// If not seen before in the file or in the database, then set the validation to pass
else {
$validator_status = [
'title' => 'Unique Trait Name + Method Short Name + Unit combination',
'status' => 'pass',
'details' => 'Confirmed that the current trait being validated is unique.'
'case' => 'Confirmed that the current trait being validated is unique',
'valid' => TRUE,
'failedItems' => []
];
}
return $validator_status;
Expand Down
46 changes: 23 additions & 23 deletions trpcultivate_phenotypes/src/Plugin/Validators/EmptyCell.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace Drupal\trpcultivate_phenotypes\Plugin\Validators;

use Drupal\trpcultivate_phenotypes\TripalCultivateValidator\TripalCultivatePhenotypesValidatorBase;
use Drupal\trpcultivate_phenotypes\TripalCultivateValidator\ValidatorTraits\ColumnIndices;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

Expand All @@ -17,21 +18,17 @@
* @TripalCultivatePhenotypesValidator(
* id = "empty_cell",
* validator_name = @Translation("Empty Cell Validator"),
* validator_scope = "FILE ROW",
* input_types = {"header-row", "data-row"},
* )
*/
class EmptyCell extends TripalCultivatePhenotypesValidatorBase implements ContainerFactoryPluginInterface {

/**
* An associative array containing the needed context, which is dependant
* on the validator. For example, instead of validating each cell by default,
* a validator may need a list of indices which correspond to the columns in
* the row for which the validator should act on.
*
* This validator requires the following keys:
* - indices => an array of indices corresponding to the cells in $row_values to act on
* This validator requires the following validator traits:
* - ColumnIndices: Gets an array of indices corresponding to the cells in
* $row_values to act on.
*/
public array $context = [];
use ColumnIndices;

/**
* Constructor.
Expand Down Expand Up @@ -60,26 +57,28 @@ public static function create(ContainerInterface $container, array $configuratio
*
* @return array
* An associative array with the following keys.
* - title: string, section or title of the validation as it appears in the result window.
* - status: string, pass if it passed the validation check/test, fail string otherwise and todo string if validation was not applied.
* - details: details about the offending field/value.
* - case: a developer focused string describing the case checked.
* - valid: FALSE if any of the cells being checked are empty and TRUE otherwise.
* - failedItems: an array of "items" that failed with the following keys, to
* be used in the message to the user. This is an empty array if the data row input was valid.
* - empty_indices: A list of indices which were checked and found to be empty
*/
public function validateRow($row_values) {

// Set our context which was configured for this validator
$context = $this->context;
// Grab our indices
$indices = $this->getIndices();

// Check the indices provided are valid in the context of the row.
// Will throw an exception if there's a problem
$this->checkIndices($row_values, $context['indices']);
$this->checkIndices($row_values, $indices);

$empty = FALSE;
$failed_indices = [];
// Iterate through our array of row values
foreach($row_values as $index => $cell) {
// Only validate the values in which their index is also within our
// context array of indices
if (in_array($index, $context['indices'])) {
if (in_array($index, $indices)) {
// First trim the contents of our cell in case we have whitespace
$cell = trim($cell);
// Check if our content is empty and report an error if it is
Expand All @@ -91,17 +90,18 @@ public function validateRow($row_values) {
}
// Check if empty values were found that should not be empty
if ($empty) {
$failed_list = implode(', ', $failed_indices);
$validator_status = [
'title' => 'Empty value found in required column(s)',
'status' => 'fail',
'details' => 'Empty values at index: ' . $failed_list
'case' => 'Empty value found in required column(s)',
'valid' => FALSE,
'failedItems' => [
'empty_indices' => $failed_indices
]
];
} else {
$validator_status = [
'title' => 'No empty values found in required column(s)',
'status' => 'pass',
'details' => ''
'case' => 'No empty values found in required column(s)',
'valid' => TRUE,
'failedItems' => []
];
}
return $validator_status;
Expand Down
Loading