259 lines
7.0 KiB
PHP
259 lines
7.0 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace App\Libraries;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Test Validation Service
|
||
|
|
*
|
||
|
|
* Validates TestType, ResultType, and RefType combinations
|
||
|
|
* according to business rules for CLQMS test definitions.
|
||
|
|
*/
|
||
|
|
class TestValidationService
|
||
|
|
{
|
||
|
|
/**
|
||
|
|
* Valid TestType to ResultType mappings
|
||
|
|
*/
|
||
|
|
private const TEST_TYPE_RESULT_TYPES = [
|
||
|
|
'TEST' => ['NMRIC', 'RANGE', 'TEXT', 'VSET'],
|
||
|
|
'PARAM' => ['NMRIC', 'RANGE', 'TEXT', 'VSET'],
|
||
|
|
'CALC' => ['NMRIC'],
|
||
|
|
'GROUP' => ['NORES'],
|
||
|
|
'TITLE' => ['NORES'],
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Valid ResultType to RefType mappings
|
||
|
|
*/
|
||
|
|
private const RESULT_TYPE_REF_TYPES = [
|
||
|
|
'NMRIC' => ['RANGE', 'THOLD'],
|
||
|
|
'RANGE' => ['RANGE', 'THOLD'],
|
||
|
|
'VSET' => ['VSET'],
|
||
|
|
'TEXT' => ['TEXT'],
|
||
|
|
'NORES' => ['NOREF'],
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Reference table mapping based on ResultType and RefType
|
||
|
|
*/
|
||
|
|
private const REFERENCE_TABLES = [
|
||
|
|
'NMRIC' => [
|
||
|
|
'RANGE' => 'refnum',
|
||
|
|
'THOLD' => 'refnum',
|
||
|
|
],
|
||
|
|
'RANGE' => [
|
||
|
|
'RANGE' => 'refnum',
|
||
|
|
'THOLD' => 'refnum',
|
||
|
|
],
|
||
|
|
'VSET' => [
|
||
|
|
'VSET' => 'reftxt',
|
||
|
|
],
|
||
|
|
'TEXT' => [
|
||
|
|
'TEXT' => 'reftxt',
|
||
|
|
],
|
||
|
|
'NORES' => [
|
||
|
|
'NOREF' => null,
|
||
|
|
],
|
||
|
|
];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate TestType and ResultType combination
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @param string $resultType
|
||
|
|
* @return array ['valid' => bool, 'error' => string|null]
|
||
|
|
*/
|
||
|
|
public static function validateTestTypeResultType(string $testType, string $resultType): array
|
||
|
|
{
|
||
|
|
$testType = strtoupper($testType);
|
||
|
|
$resultType = strtoupper($resultType);
|
||
|
|
|
||
|
|
if (!isset(self::TEST_TYPE_RESULT_TYPES[$testType])) {
|
||
|
|
return [
|
||
|
|
'valid' => false,
|
||
|
|
'error' => "Invalid TestType '{$testType}'. Allowed: TEST, PARAM, CALC, GROUP, TITLE"
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
$validResultTypes = self::TEST_TYPE_RESULT_TYPES[$testType];
|
||
|
|
|
||
|
|
if (!in_array($resultType, $validResultTypes, true)) {
|
||
|
|
return [
|
||
|
|
'valid' => false,
|
||
|
|
'error' => "Invalid ResultType '{$resultType}' for TestType '{$testType}'. Allowed: " . implode(', ', $validResultTypes)
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
return ['valid' => true, 'error' => null];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate ResultType and RefType combination
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @param string $refType
|
||
|
|
* @return array ['valid' => bool, 'error' => string|null]
|
||
|
|
*/
|
||
|
|
public static function validateResultTypeRefType(string $resultType, string $refType): array
|
||
|
|
{
|
||
|
|
$resultType = strtoupper($resultType);
|
||
|
|
$refType = strtoupper($refType);
|
||
|
|
|
||
|
|
if (!isset(self::RESULT_TYPE_REF_TYPES[$resultType])) {
|
||
|
|
return [
|
||
|
|
'valid' => false,
|
||
|
|
'error' => "Invalid ResultType '{$resultType}'. Allowed: NMRIC, RANGE, TEXT, VSET, NORES"
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
$validRefTypes = self::RESULT_TYPE_REF_TYPES[$resultType];
|
||
|
|
|
||
|
|
if (!in_array($refType, $validRefTypes, true)) {
|
||
|
|
return [
|
||
|
|
'valid' => false,
|
||
|
|
'error' => "Invalid RefType '{$refType}' for ResultType '{$resultType}'. Allowed: " . implode(', ', $validRefTypes)
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
return ['valid' => true, 'error' => null];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Validate complete test type combination
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @param string $resultType
|
||
|
|
* @param string $refType
|
||
|
|
* @return array ['valid' => bool, 'error' => string|null]
|
||
|
|
*/
|
||
|
|
public static function validate(string $testType, string $resultType, string $refType): array
|
||
|
|
{
|
||
|
|
// First validate TestType and ResultType
|
||
|
|
$testResultValidation = self::validateTestTypeResultType($testType, $resultType);
|
||
|
|
if (!$testResultValidation['valid']) {
|
||
|
|
return $testResultValidation;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Then validate ResultType and RefType
|
||
|
|
return self::validateResultTypeRefType($resultType, $refType);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get valid ResultTypes for a TestType
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @return array
|
||
|
|
*/
|
||
|
|
public static function getValidResultTypes(string $testType): array
|
||
|
|
{
|
||
|
|
$testType = strtoupper($testType);
|
||
|
|
return self::TEST_TYPE_RESULT_TYPES[$testType] ?? [];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get valid RefTypes for a ResultType
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @return array
|
||
|
|
*/
|
||
|
|
public static function getValidRefTypes(string $resultType): array
|
||
|
|
{
|
||
|
|
$resultType = strtoupper($resultType);
|
||
|
|
return self::RESULT_TYPE_REF_TYPES[$resultType] ?? [];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get reference table name based on ResultType and RefType
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @param string $refType
|
||
|
|
* @return string|null Returns table name or null if no reference table needed
|
||
|
|
*/
|
||
|
|
public static function getReferenceTable(string $resultType, string $refType): ?string
|
||
|
|
{
|
||
|
|
$resultType = strtoupper($resultType);
|
||
|
|
$refType = strtoupper($refType);
|
||
|
|
|
||
|
|
return self::REFERENCE_TABLES[$resultType][$refType] ?? null;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if a test needs reference ranges
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function needsReferenceRanges(string $resultType): bool
|
||
|
|
{
|
||
|
|
$resultType = strtoupper($resultType);
|
||
|
|
return $resultType !== 'NORES';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if a test uses refnum table
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @param string $refType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function usesRefNum(string $resultType, string $refType): bool
|
||
|
|
{
|
||
|
|
return self::getReferenceTable($resultType, $refType) === 'refnum';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if a test uses reftxt table
|
||
|
|
*
|
||
|
|
* @param string $resultType
|
||
|
|
* @param string $refType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function usesRefTxt(string $resultType, string $refType): bool
|
||
|
|
{
|
||
|
|
return self::getReferenceTable($resultType, $refType) === 'reftxt';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if TestType is CALC
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function isCalc(string $testType): bool
|
||
|
|
{
|
||
|
|
return strtoupper($testType) === 'CALC';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if TestType is GROUP
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function isGroup(string $testType): bool
|
||
|
|
{
|
||
|
|
return strtoupper($testType) === 'GROUP';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if TestType is TITLE
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function isTitle(string $testType): bool
|
||
|
|
{
|
||
|
|
return strtoupper($testType) === 'TITLE';
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if TestType is TEST or PARAM (technical tests)
|
||
|
|
*
|
||
|
|
* @param string $testType
|
||
|
|
* @return bool
|
||
|
|
*/
|
||
|
|
public static function isTechnicalTest(string $testType): bool
|
||
|
|
{
|
||
|
|
$testType = strtoupper($testType);
|
||
|
|
return in_array($testType, ['TEST', 'PARAM'], true);
|
||
|
|
}
|
||
|
|
}
|