2026-03-16 07:24:50 +07:00
< ? php
namespace App\Controllers\Test ;
use App\Controllers\BaseController ;
use App\Libraries\TestValidationService ;
use App\Libraries\ValueSet ;
use App\Traits\ResponseTrait ;
class TestsController extends BaseController
{
use ResponseTrait ;
protected $model ;
protected $modelCal ;
protected $modelGrp ;
protected $modelMap ;
protected $modelMapDetail ;
protected $modelRefNum ;
protected $modelRefTxt ;
protected $rules ;
public function __construct ()
{
$this -> model = new \App\Models\Test\TestDefSiteModel ;
$this -> modelCal = new \App\Models\Test\TestDefCalModel ;
$this -> modelGrp = new \App\Models\Test\TestDefGrpModel ;
$this -> modelMap = new \App\Models\Test\TestMapModel ;
$this -> modelMapDetail = new \App\Models\Test\TestMapDetailModel ;
$this -> modelRefNum = new \App\Models\RefRange\RefNumModel ;
$this -> modelRefTxt = new \App\Models\RefRange\RefTxtModel ;
2026-04-01 13:28:44 +07:00
$this -> rules = [
'TestSiteCode' => 'required' ,
'TestSiteName' => 'required' ,
'TestType' => 'required' ,
];
2026-03-16 07:24:50 +07:00
}
public function index ()
{
$search = $this -> request -> getGet ( 'search' );
2026-03-25 11:37:17 +07:00
$filters = [
'SiteID' => $this -> request -> getGet ( 'SiteID' ),
'TestType' => $this -> request -> getGet ( 'TestType' ),
'isVisibleScr' => $this -> request -> getGet ( 'isVisibleScr' ),
'isVisibleRpt' => $this -> request -> getGet ( 'isVisibleRpt' ),
2026-03-16 07:24:50 +07:00
'TestSiteName' => $this -> request -> getGet ( 'TestSiteName' ),
'TestSiteCode' => $this -> request -> getGet ( 'TestSiteCode' ),
'search' => $search ,
];
$rows = $this -> model -> getTestsWithRelations ( $filters );
if ( empty ( $rows )) {
return $this -> respond ([
'status' => 'success' ,
'message' => 'No data.' ,
'data' => [],
], 200 );
}
$rows = ValueSet :: transformLabels ( $rows , [
'TestType' => 'test_type' ,
]);
return $this -> respond ([
'status' => 'success' ,
'message' => 'Data fetched successfully' ,
'data' => $rows ,
], 200 );
}
public function show ( $id = null )
{
if ( ! $id ) {
return $this -> failValidationErrors ( 'TestSiteID is required' );
}
$row = $this -> model -> getTestById ( $id );
if ( ! $row ) {
return $this -> respond ([
'status' => 'success' ,
'message' => 'No data.' ,
'data' => null ,
], 200 );
}
$typeCode = $row [ 'TestType' ] ? ? '' ;
2026-04-02 04:52:50 +07:00
if ( $typeCode === 'CALC' ) {
$row [ 'testdefcal' ] = $this -> modelCal -> getByTestSiteID ( $id );
2026-04-02 09:06:42 +07:00
$row [ 'testdefgrp' ] = [
'members' => $this -> modelGrp -> getGroupMembers ( $id ),
];
2026-04-02 04:52:50 +07:00
} elseif ( $typeCode === 'GROUP' ) {
2026-04-02 09:06:42 +07:00
$row [ 'testdefgrp' ] = [
'members' => $this -> modelGrp -> getGroupMembers ( $id ),
];
2026-03-25 14:06:00 +07:00
} elseif ( $typeCode !== 'TITLE' ) {
$refType = $row [ 'RefType' ] ? ? '' ;
$resultType = $row [ 'ResultType' ] ? ? '' ;
if ( TestValidationService :: usesRefNum ( $resultType , $refType )) {
$row [ 'refnum' ] = $this -> modelRefNum -> getFormattedByTestSiteID ( $id );
}
if ( TestValidationService :: usesRefTxt ( $resultType , $refType )) {
$row [ 'reftxt' ] = $this -> modelRefTxt -> getFormattedByTestSiteID ( $id );
}
}
2026-04-06 11:24:58 +07:00
// Keep /api/test payload focused on test definition fields.
unset ( $row [ 'testmap' ]);
return $this -> respond ([
'status' => 'success' ,
'message' => 'Data fetched successfully' ,
'data' => $row ,
], 200 );
2026-03-16 07:24:50 +07:00
}
public function create ()
{
$input = $this -> request -> getJSON ( true );
if ( ! $this -> validateData ( $input , $this -> rules )) {
return $this -> failValidationErrors ( $this -> validator -> getErrors ());
}
$testType = $input [ 'TestType' ] ? ? '' ;
$details = $input [ 'details' ] ? ? $input ;
$resultType = $details [ 'ResultType' ] ? ? '' ;
$refType = $details [ 'RefType' ] ? ? '' ;
if ( TestValidationService :: isCalc ( $testType )) {
$resultType = 'NMRIC' ;
$refType = $refType ? : 'RANGE' ;
} elseif ( TestValidationService :: isGroup ( $testType ) || TestValidationService :: isTitle ( $testType )) {
$resultType = 'NORES' ;
$refType = 'NOREF' ;
}
if ( $resultType && $refType ) {
$validation = TestValidationService :: validate ( $testType , $resultType , $refType );
if ( ! $validation [ 'valid' ]) {
return $this -> failValidationErrors ([ 'type_validation' => $validation [ 'error' ]]);
}
}
$db = \Config\Database :: connect ();
$db -> transStart ();
try {
2026-04-01 13:28:44 +07:00
$testSiteData = [
'SiteID' => array_key_exists ( 'SiteID' , $input ) ? $input [ 'SiteID' ] : null ,
'TestSiteCode' => $input [ 'TestSiteCode' ],
'TestSiteName' => $input [ 'TestSiteName' ],
'TestType' => $input [ 'TestType' ],
'Description' => $input [ 'Description' ] ? ? null ,
'SeqScr' => array_key_exists ( 'SeqScr' , $input ) ? $input [ 'SeqScr' ] : null ,
'SeqRpt' => array_key_exists ( 'SeqRpt' , $input ) ? $input [ 'SeqRpt' ] : null ,
'IndentLeft' => $input [ 'IndentLeft' ] ? ? 0 ,
2026-03-25 11:37:17 +07:00
'FontStyle' => $input [ 'FontStyle' ] ? ? null ,
'isVisibleScr' => $input [ 'isVisibleScr' ] ? ? 1 ,
'isVisibleRpt' => $input [ 'isVisibleRpt' ] ? ? 1 ,
'isCountStat' => $input [ 'isCountStat' ] ? ? 1 ,
2026-03-25 15:42:52 +07:00
'isRequestable' => $input [ 'isRequestable' ] ? ? 1 ,
2026-03-16 07:24:50 +07:00
'StartDate' => $input [ 'StartDate' ] ? ? date ( 'Y-m-d H:i:s' ),
];
2026-03-16 15:58:56 +07:00
$id = $this -> model -> insert ( $testSiteData );
if ( ! $id ) {
$dbError = $db -> error ();
log_message ( 'error' , 'Test insert failed: ' . json_encode ( $dbError , JSON_UNESCAPED_SLASHES ));
$message = $dbError [ 'message' ] ? ? 'Failed to insert main test definition' ;
throw new \Exception ( 'Failed to insert main test definition: ' . $message );
}
$this -> handleDetails ( $id , $input , 'insert' );
2026-03-16 07:24:50 +07:00
$db -> transComplete ();
2026-03-16 15:58:56 +07:00
if ( $db -> transStatus () === false ) {
$dbError = $db -> error ();
$lastQuery = $db -> showLastQuery ();
log_message ( 'error' , 'TestController transaction failed: ' . json_encode ([
'error' => $dbError ,
'last_query' => $lastQuery ,
], JSON_UNESCAPED_SLASHES ));
return $this -> failServerError ( 'Transaction failed' );
}
2026-03-16 07:24:50 +07:00
return $this -> respondCreated ([
'status' => 'created' ,
'message' => 'Test created successfully' ,
'data' => [ 'TestSiteId' => $id ],
]);
} catch ( \Exception $e ) {
$db -> transRollback ();
return $this -> failServerError ( 'Something went wrong: ' . $e -> getMessage ());
}
}
public function update ( $id = null )
{
$input = $this -> request -> getJSON ( true );
if ( ! $id && isset ( $input [ 'TestSiteID' ])) {
$id = $input [ 'TestSiteID' ];
}
if ( ! $id ) {
return $this -> failValidationErrors ( 'TestSiteID is required.' );
}
$existing = $this -> model -> find ( $id );
if ( ! $existing ) {
return $this -> failNotFound ( 'Test not found' );
}
$testType = $input [ 'TestType' ] ? ? $existing [ 'TestType' ] ? ? '' ;
$details = $input [ 'details' ] ? ? $input ;
$resultType = $details [ 'ResultType' ] ? ? $existing [ 'ResultType' ] ? ? '' ;
$refType = $details [ 'RefType' ] ? ? $existing [ 'RefType' ] ? ? '' ;
if ( TestValidationService :: isCalc ( $testType )) {
$resultType = 'NMRIC' ;
$refType = $refType ? : 'RANGE' ;
} elseif ( TestValidationService :: isGroup ( $testType ) || TestValidationService :: isTitle ( $testType )) {
$resultType = 'NORES' ;
$refType = 'NOREF' ;
}
if ( $resultType && $refType ) {
$validation = TestValidationService :: validate ( $testType , $resultType , $refType );
if ( ! $validation [ 'valid' ]) {
return $this -> failValidationErrors ([ 'type_validation' => $validation [ 'error' ]]);
}
}
$db = \Config\Database :: connect ();
$db -> transStart ();
try {
$testSiteData = [];
$allowedUpdateFields = [
'TestSiteCode' ,
'TestSiteName' ,
'TestType' ,
'Description' ,
'SeqScr' ,
'SeqRpt' ,
'IndentLeft' ,
'FontStyle' ,
2026-03-25 15:42:52 +07:00
'isVisibleScr' ,
'isVisibleRpt' ,
'isCountStat' ,
'isRequestable' ,
'StartDate' ,
];
2026-03-16 07:24:50 +07:00
foreach ( $allowedUpdateFields as $field ) {
if ( isset ( $input [ $field ])) {
$testSiteData [ $field ] = $input [ $field ];
}
}
if ( ! empty ( $testSiteData )) {
$this -> model -> update ( $id , $testSiteData );
}
$this -> handleDetails ( $id , $input , 'update' );
$db -> transComplete ();
if ( $db -> transStatus () === false ) {
return $this -> failServerError ( 'Transaction failed' );
}
return $this -> respond ([
'status' => 'success' ,
'message' => 'Test updated successfully' ,
'data' => [ 'TestSiteId' => $id ],
]);
} catch ( \Exception $e ) {
$db -> transRollback ();
return $this -> failServerError ( 'Something went wrong: ' . $e -> getMessage ());
}
}
public function delete ( $id = null )
{
$input = $this -> request -> getJSON ( true );
if ( ! $id && isset ( $input [ 'TestSiteID' ])) {
$id = $input [ 'TestSiteID' ];
}
if ( ! $id ) {
return $this -> failValidationErrors ( 'TestSiteID is required.' );
}
$existing = $this -> model -> find ( $id );
if ( ! $existing ) {
return $this -> failNotFound ( 'Test not found' );
}
if ( ! empty ( $existing [ 'EndDate' ])) {
return $this -> failValidationErrors ( 'Test is already disabled' );
}
$db = \Config\Database :: connect ();
$db -> transStart ();
try {
$now = date ( 'Y-m-d H:i:s' );
$this -> model -> update ( $id , [ 'EndDate' => $now ]);
$testType = $existing [ 'TestType' ];
$typeCode = $testType ;
if ( TestValidationService :: isCalc ( $typeCode )) {
$this -> modelCal -> disableByTestSiteID ( $id );
$this -> modelGrp -> disableByTestSiteID ( $id );
} elseif ( TestValidationService :: isGroup ( $typeCode )) {
$this -> modelGrp -> disableByTestSiteID ( $id );
} elseif ( TestValidationService :: isTechnicalTest ( $typeCode )) {
$this -> modelRefNum -> disableByTestSiteID ( $id );
$this -> modelRefTxt -> disableByTestSiteID ( $id );
}
// Disable testmap by test code
$testSiteCode = $existing [ 'TestSiteCode' ] ? ? null ;
if ( $testSiteCode ) {
$existingMaps = $this -> modelMap -> getMappingsByTestCode ( $testSiteCode );
foreach ( $existingMaps as $existingMap ) {
$this -> modelMapDetail -> disableByTestMapID ( $existingMap [ 'TestMapID' ]);
$this -> modelMap -> update ( $existingMap [ 'TestMapID' ], [ 'EndDate' => $now ]);
}
}
$db -> transComplete ();
if ( $db -> transStatus () === false ) {
return $this -> failServerError ( 'Transaction failed' );
}
return $this -> respond ([
'status' => 'success' ,
'message' => 'Test disabled successfully' ,
'data' => [ 'TestSiteId' => $id , 'EndDate' => $now ],
]);
} catch ( \Exception $e ) {
$db -> transRollback ();
return $this -> failServerError ( 'Something went wrong: ' . $e -> getMessage ());
}
}
private function handleDetails ( $testSiteID , $input , $action )
{
$testTypeID = $input [ 'TestType' ] ? ? null ;
$testSiteCode = null ;
if ( ! $testTypeID && $action === 'update' ) {
$existing = $this -> model -> find ( $testSiteID );
$testTypeID = $existing [ 'TestType' ] ? ? null ;
$testSiteCode = $existing [ 'TestSiteCode' ] ? ? null ;
}
if ( ! $testTypeID ) {
return ;
}
$typeCode = $testTypeID ;
2026-04-01 13:28:44 +07:00
$details = $input [ 'details' ] ? ? $input ;
$details [ 'TestSiteID' ] = $testSiteID ;
$details [ 'SiteID' ] = array_key_exists ( 'SiteID' , $input ) ? $input [ 'SiteID' ] : null ;
2026-03-16 07:24:50 +07:00
switch ( $typeCode ) {
case 'CALC' :
$this -> saveCalcDetails ( $testSiteID , $details , $input , $action );
break ;
case 'GROUP' :
$this -> saveGroupDetails ( $testSiteID , $details , $input , $action );
break ;
2026-04-06 11:24:58 +07:00
case 'TITLE' :
break ;
2026-03-16 07:24:50 +07:00
case 'TEST' :
case 'PARAM' :
default :
$this -> saveTechDetails ( $testSiteID , $details , $action , $typeCode );
if ( in_array ( $typeCode , [ 'TEST' , 'PARAM' ]) && isset ( $details [ 'RefType' ])) {
$refType = ( string ) $details [ 'RefType' ];
$resultType = $details [ 'ResultType' ] ? ? '' ;
2026-04-01 13:28:44 +07:00
if ( TestValidationService :: usesRefNum ( $resultType , $refType ) && isset ( $input [ 'refnum' ]) && is_array ( $input [ 'refnum' ])) {
$this -> saveRefNumRanges ( $testSiteID , $input [ 'refnum' ], $action , array_key_exists ( 'SiteID' , $input ) ? $input [ 'SiteID' ] : null );
}
if ( TestValidationService :: usesRefTxt ( $resultType , $refType ) && isset ( $input [ 'reftxt' ]) && is_array ( $input [ 'reftxt' ])) {
$this -> saveRefTxtRanges ( $testSiteID , $input [ 'reftxt' ], $action , array_key_exists ( 'SiteID' , $input ) ? $input [ 'SiteID' ] : null );
}
}
2026-03-16 07:24:50 +07:00
break ;
}
2026-04-06 11:24:58 +07:00
}
2026-03-16 07:24:50 +07:00
2026-04-01 13:28:44 +07:00
private function saveTechDetails ( $testSiteID , $data , $action , $typeCode )
{
$techData = [
'DisciplineID' => $data [ 'DisciplineID' ] ? ? null ,
'DepartmentID' => $data [ 'DepartmentID' ] ? ? null ,
'ResultType' => $data [ 'ResultType' ] ? ? null ,
'RefType' => $data [ 'RefType' ] ? ? null ,
'VSet' => $data [ 'VSet' ] ? ? null ,
'ReqQty' => $data [ 'ReqQty' ] ? ? null ,
'ReqQtyUnit' => $data [ 'ReqQtyUnit' ] ? ? null ,
'Unit1' => $data [ 'Unit1' ] ? ? null ,
'Factor' => $data [ 'Factor' ] ? ? null ,
'Unit2' => $data [ 'Unit2' ] ? ? null ,
'Decimal' => array_key_exists ( 'Decimal' , $data ) ? $data [ 'Decimal' ] : null ,
'CollReq' => $data [ 'CollReq' ] ? ? null ,
'Method' => $data [ 'Method' ] ? ? null ,
'ExpectedTAT' => $data [ 'ExpectedTAT' ] ? ? null ,
];
$this -> model -> update ( $testSiteID , $techData );
}
private function saveRefNumRanges ( $testSiteID , $ranges , $action , $siteID )
{
2026-03-16 07:24:50 +07:00
if ( $action === 'update' ) {
$this -> modelRefNum -> disableByTestSiteID ( $testSiteID );
}
$this -> modelRefNum -> batchInsert ( $testSiteID , $siteID , $ranges );
}
private function saveRefTxtRanges ( $testSiteID , $ranges , $action , $siteID )
{
if ( $action === 'update' ) {
$this -> modelRefTxt -> disableByTestSiteID ( $testSiteID );
}
$this -> modelRefTxt -> batchInsert ( $testSiteID , $siteID , $ranges );
}
2026-04-01 13:28:44 +07:00
private function saveCalcDetails ( $testSiteID , $data , $input , $action )
{
$calcData = [
'TestSiteID' => $testSiteID ,
'DisciplineID' => $data [ 'DisciplineID' ] ? ? null ,
'DepartmentID' => $data [ 'DepartmentID' ] ? ? null ,
'FormulaCode' => $data [ 'FormulaCode' ] ? ? $data [ 'Formula' ] ? ? null ,
'ResultType' => 'NMRIC' ,
'RefType' => $data [ 'RefType' ] ? ? 'RANGE' ,
'Unit1' => $data [ 'Unit1' ] ? ? $data [ 'ResultUnit' ] ? ? null ,
'Factor' => $data [ 'Factor' ] ? ? null ,
'Unit2' => $data [ 'Unit2' ] ? ? null ,
'Decimal' => array_key_exists ( 'Decimal' , $data ) ? $data [ 'Decimal' ] : null ,
'Method' => $data [ 'Method' ] ? ? null ,
];
2026-03-16 07:24:50 +07:00
if ( $action === 'update' ) {
$exists = $this -> modelCal -> existsByTestSiteID ( $testSiteID );
if ( $exists ) {
$this -> modelCal -> update ( $exists [ 'TestCalID' ], $calcData );
} else {
$this -> modelCal -> insert ( $calcData );
}
} else {
$this -> modelCal -> insert ( $calcData );
}
if ( $action === 'update' ) {
$this -> modelGrp -> disableByTestSiteID ( $testSiteID );
}
2026-04-02 04:52:50 +07:00
$memberIDs = $this -> resolveMemberIDs ( $input );
2026-03-16 07:24:50 +07:00
// Validate member IDs before insertion
$validation = $this -> validateMemberIDs ( $memberIDs );
if ( ! $validation [ 'valid' ]) {
throw new \Exception ( 'Invalid member TestSiteID(s): ' . implode ( ', ' , $validation [ 'invalid' ]) . '. Make sure to use TestSiteID, not SeqScr or other values.' );
}
foreach ( $memberIDs as $memberID ) {
$this -> modelGrp -> insert ([
'TestSiteID' => $testSiteID ,
'Member' => $memberID ,
]);
}
}
2026-04-02 04:52:50 +07:00
private function resolveMemberIDs ( array $input ) : array
{
$memberIDs = [];
2026-04-02 09:06:42 +07:00
$rawMembers = $input [ 'testdefgrp' ][ 'members' ] ? ? [];
2026-04-02 04:52:50 +07:00
if ( is_array ( $rawMembers )) {
foreach ( $rawMembers as $member ) {
if ( is_array ( $member )) {
$rawID = $member [ 'TestSiteID' ] ? ? null ;
} else {
$rawID = is_numeric ( $member ) ? $member : null ;
2026-03-16 07:24:50 +07:00
}
if ( $rawID !== null && is_numeric ( $rawID )) {
$memberIDs [] = ( int ) $rawID ;
}
}
}
$memberIDs = array_values ( array_unique ( array_filter ( $memberIDs )));
return $memberIDs ;
}
/**
* Validate that member IDs exist in testdefsite table
*
* @ param array $memberIDs Array of TestSiteID values to validate
* @ return array [ 'valid' => bool , 'invalid' => array ]
*/
private function validateMemberIDs ( array $memberIDs ) : array
{
if ( empty ( $memberIDs )) {
return [ 'valid' => true , 'invalid' => []];
}
$existing = $this -> model -> whereIn ( 'TestSiteID' , $memberIDs )
-> where ( 'EndDate IS NULL' )
-> findAll ();
$existingIDs = array_column ( $existing , 'TestSiteID' );
$invalidIDs = array_diff ( $memberIDs , $existingIDs );
return [
'valid' => empty ( $invalidIDs ),
'invalid' => array_values ( $invalidIDs )
];
}
2026-04-02 04:52:50 +07:00
private function saveGroupDetails ( $testSiteID , $data , $input , $action )
{
if ( $action === 'update' ) {
$this -> modelGrp -> disableByTestSiteID ( $testSiteID );
}
$memberIDs = $this -> resolveMemberIDs ( $input );
2026-03-16 07:24:50 +07:00
// Validate member IDs before insertion
$validation = $this -> validateMemberIDs ( $memberIDs );
if ( ! $validation [ 'valid' ]) {
throw new \Exception ( 'Invalid member TestSiteID(s): ' . implode ( ', ' , $validation [ 'invalid' ]) . '. Make sure to use TestSiteID, not SeqScr or other values.' );
}
foreach ( $memberIDs as $memberID ) {
$this -> modelGrp -> insert ([
'TestSiteID' => $testSiteID ,
'Member' => $memberID ,
]);
}
}
2026-04-01 20:28:12 +07:00
private function saveTestMap ( $testSiteID , $testSiteCode , $mappings , $action )
{
if ( $action === 'update' && $testSiteCode ) {
2026-03-16 07:24:50 +07:00
// Find existing mappings by test code through testmapdetail
$existingMaps = $this -> modelMap -> getMappingsByTestCode ( $testSiteCode );
foreach ( $existingMaps as $existingMap ) {
$this -> modelMapDetail -> disableByTestMapID ( $existingMap [ 'TestMapID' ]);
}
// Soft delete the testmap headers
foreach ( $existingMaps as $existingMap ) {
$this -> modelMap -> update ( $existingMap [ 'TestMapID' ], [ 'EndDate' => date ( 'Y-m-d H:i:s' )]);
2026-04-01 20:28:12 +07:00
}
}
foreach ( $this -> normalizeTestMapPayload ( $mappings ) as $map ) {
$mapData = [
'HostType' => $map [ 'HostType' ] ? ? null ,
'HostID' => $map [ 'HostID' ] ? ? null ,
'ClientType' => $map [ 'ClientType' ] ? ? null ,
'ClientID' => $map [ 'ClientID' ] ? ? null ,
];
$testMapID = $this -> modelMap -> insert ( $mapData );
if ( ! $testMapID ) {
continue ;
}
foreach ( $this -> extractTestMapDetails ( $map ) as $detail ) {
$detailData = [
'TestMapID' => $testMapID ,
'HostTestCode' => $detail [ 'HostTestCode' ] ? ? null ,
'HostTestName' => $detail [ 'HostTestName' ] ? ? null ,
'ConDefID' => $detail [ 'ConDefID' ] ? ? null ,
'ClientTestCode' => $detail [ 'ClientTestCode' ] ? ? null ,
'ClientTestName' => $detail [ 'ClientTestName' ] ? ? null ,
];
$this -> modelMapDetail -> insert ( $detailData );
}
}
}
private function normalizeTestMapPayload ( $mappings ) : array
{
if ( ! is_array ( $mappings )) {
return [];
}
if ( $this -> isAssoc ( $mappings )) {
return [ $mappings ];
}
return array_values ( array_filter ( $mappings , static fn ( $map ) => is_array ( $map )));
}
private function extractTestMapDetails ( array $map ) : array
{
if ( isset ( $map [ 'details' ]) && is_array ( $map [ 'details' ])) {
return array_values ( array_filter ( $map [ 'details' ], static fn ( $detail ) => is_array ( $detail )));
}
$flatDetail = [
'HostTestCode' => $map [ 'HostTestCode' ] ? ? null ,
'HostTestName' => $map [ 'HostTestName' ] ? ? null ,
'ConDefID' => $map [ 'ConDefID' ] ? ? null ,
'ClientTestCode' => $map [ 'ClientTestCode' ] ? ? null ,
'ClientTestName' => $map [ 'ClientTestName' ] ? ? null ,
];
foreach ( $flatDetail as $value ) {
if ( $value !== null && $value !== '' ) {
return [ $flatDetail ];
}
}
return [];
}
private function isAssoc ( array $array ) : bool
{
if ( $array === []) {
return false ;
}
return array_keys ( $array ) !== range ( 0 , count ( $array ) - 1 );
}
}