- Remove pagination from ValueSetController::index() and ValueSetModel::getValueSets()
- Delete duplicate AGENTS.md documentation (consolidated into CLAUDE.md)
- Update .gitignore to exclude .claude folder
- Add CLAUDE.md with comprehensive agent instructions for Valueset queries
- Document new Lookups static library in README.md
650 lines
19 KiB
PHP
650 lines
19 KiB
PHP
<?php
|
|
namespace App\Libraries;
|
|
|
|
/**
|
|
* Static Lookup Values
|
|
* All predefined lookup values stored as constants for easy access.
|
|
* No database queries - all data is hardcoded.
|
|
* Based on valuesetdef and valueset tables.
|
|
*/
|
|
class Lookups {
|
|
|
|
// VSetID 1: Workstation Type
|
|
const WS_TYPE = [
|
|
'0' => 'Primary',
|
|
'1' => 'Secondary'
|
|
];
|
|
|
|
// VSetID 2: Enable/Disable
|
|
const ENABLE_DISABLE = [
|
|
'0' => 'Disabled',
|
|
'1' => 'Enabled'
|
|
];
|
|
|
|
// VSetID 3: Gender
|
|
const GENDER = [
|
|
'1' => 'Female',
|
|
'2' => 'Male',
|
|
'3' => 'Unknown'
|
|
];
|
|
|
|
// VSetID 4: Marital Status
|
|
const MARITAL_STATUS = [
|
|
'A' => 'Separated',
|
|
'D' => 'Divorced',
|
|
'M' => 'Married',
|
|
'S' => 'Single',
|
|
'W' => 'Widowed',
|
|
'B' => 'Unmarried',
|
|
'U' => 'Unknown',
|
|
'O' => 'Other'
|
|
];
|
|
|
|
// VSetID 5: Death Indicator
|
|
const DEATH_INDICATOR = [
|
|
'Y' => 'Death',
|
|
'N' => 'Life'
|
|
];
|
|
|
|
// VSetID 6: Identifier Type
|
|
const IDENTIFIER_TYPE = [
|
|
'KTP' => 'Kartu Tanda Penduduk',
|
|
'PASS' => 'Passport',
|
|
'SSN' => 'Social Security Number',
|
|
'SIM' => 'Surat Izin Mengemudi',
|
|
'KTAS' => 'Kartu Izin Tinggal Terbatas'
|
|
];
|
|
|
|
// VSetID 7: Operation (CRUD)
|
|
const OPERATION = [
|
|
'Create' => 'Create record',
|
|
'Read' => 'Read record/field',
|
|
'Update' => 'Update record/field',
|
|
'Delete' => 'Delete record/field'
|
|
];
|
|
|
|
// VSetID 8: DID Type
|
|
const DID_TYPE = [
|
|
'WDID' => 'Windows Device ID',
|
|
'AAID' => 'Android AAID',
|
|
'IDFA' => 'iOS IDFA'
|
|
];
|
|
|
|
// VSetID 9: Requested Entity
|
|
const REQUESTED_ENTITY = [
|
|
'PAT' => 'Patient',
|
|
'ISN' => 'Insurance',
|
|
'ACC' => 'Account',
|
|
'DOC' => 'Doctor'
|
|
];
|
|
|
|
// VSetID 10: Order Priority
|
|
const ORDER_PRIORITY = [
|
|
'S' => 'Stat',
|
|
'A' => 'ASAP',
|
|
'R' => 'Routine',
|
|
'P' => 'Preop',
|
|
'C' => 'Callback',
|
|
'T' => 'Timing critical',
|
|
'PRN' => 'As needed'
|
|
];
|
|
|
|
// VSetID 11: Order Status
|
|
const ORDER_STATUS = [
|
|
'A' => 'Some, not all results available',
|
|
'CA' => 'Order is cancelled',
|
|
'CM' => 'Order is completed',
|
|
'DC' => 'Order was discontinued',
|
|
'ER' => 'Error, order not found',
|
|
'HD' => 'Order on hold',
|
|
'IP' => 'In process, unspecified',
|
|
'RP' => 'Order has been replaced',
|
|
'SC' => 'In process, scheduled',
|
|
'CL' => 'Closed',
|
|
'AC' => 'Archived',
|
|
'DL' => 'Deleted'
|
|
];
|
|
|
|
// VSetID 12: Location Type
|
|
const LOCATION_TYPE = [
|
|
'FCLT' => 'Facility',
|
|
'BLDG' => 'Building',
|
|
'FLOR' => 'Floor',
|
|
'POC' => 'Point of Care',
|
|
'ROOM' => 'Room',
|
|
'BED' => 'Bed',
|
|
'MOBL' => 'Mobile',
|
|
'REMT' => 'Remote'
|
|
];
|
|
|
|
// VSetID 13: Additive
|
|
const ADDITIVE = [
|
|
'Hep' => 'Heparin ammonium',
|
|
'Apro' => 'Aprotinin',
|
|
'HepCa' => 'Heparin calcium',
|
|
'H3BO3' => 'Boric acid',
|
|
'CaOxa' => 'Calcium oxalate',
|
|
'EDTA' => 'EDTA',
|
|
'Ede' => 'Edetate',
|
|
'HCl' => 'Hydrochloric acid',
|
|
'Hrdn' => 'Hirudin',
|
|
'EdeK' => 'Edetate dipotassium',
|
|
'EdeTri' => 'Tripotassium edetate',
|
|
'LiHep' => 'Heparin lithium',
|
|
'EdeNa' => 'Edetate disodium',
|
|
'NaCtrt' => 'Sodium citrate',
|
|
'NaHep' => 'Heparin sodium',
|
|
'NaF' => 'Sodium fluoride',
|
|
'Borax' => 'Sodium tetraborate',
|
|
'Mntl' => 'Mannitol',
|
|
'NaFrm' => 'Sodium formate'
|
|
];
|
|
|
|
// VSetID 14: Container Class
|
|
const CONTAINER_CLASS = [
|
|
'Pri' => 'Primary',
|
|
'Sec' => 'Secondary',
|
|
'Ter' => 'Tertiary'
|
|
];
|
|
|
|
// VSetID 15: Specimen Type
|
|
const SPECIMEN_TYPE = [
|
|
'BLD' => 'Whole blood',
|
|
'BLDA' => 'Blood arterial',
|
|
'BLDCO' => 'Cord blood',
|
|
'FBLOOD' => 'Blood, Fetal',
|
|
'CSF' => 'Cerebral spinal fluid',
|
|
'WB' => 'Blood, Whole',
|
|
'BBL' => 'Blood bag',
|
|
'SER' => 'Serum',
|
|
'PLAS' => 'Plasma',
|
|
'PLB' => 'Plasma bag',
|
|
'MUCOS' => 'Mucosa',
|
|
'MUCUS' => 'Mucus',
|
|
'UR' => 'Urine',
|
|
'RANDU' => 'Urine, Random',
|
|
'URINM' => 'Urine, Midstream'
|
|
];
|
|
|
|
// VSetID 16: Unit
|
|
const UNIT = [
|
|
'L' => 'Liter',
|
|
'mL' => 'Mili Liter',
|
|
'Pcs' => 'Pieces'
|
|
];
|
|
|
|
// VSetID 17: Generate By
|
|
const GENERATE_BY = [
|
|
'order' => 'Generate by order',
|
|
'user' => 'Generate by user'
|
|
];
|
|
|
|
// VSetID 18: Specimen Activity
|
|
const SPECIMEN_ACTIVITY = [
|
|
'SColl' => 'Collection',
|
|
'STran' => 'Transport',
|
|
'SRec' => 'Reception',
|
|
'SPrep' => 'Preparation',
|
|
'SAlqt' => 'Aliquot',
|
|
'SDisp' => 'Dispatching',
|
|
'SDest' => 'Destruction'
|
|
];
|
|
|
|
// VSetID 19: Activity Result
|
|
const ACTIVITY_RESULT = [
|
|
'0' => 'Failed',
|
|
'1' => 'Success with note',
|
|
'2' => 'Success'
|
|
];
|
|
|
|
// VSetID 20: Specimen Status
|
|
const SPECIMEN_STATUS = [
|
|
'STC' => 'To be collected',
|
|
'SCFld' => 'Collection failed',
|
|
'SCtd' => 'Collected',
|
|
'STran' => 'In-transport',
|
|
'STFld' => 'Transport failed',
|
|
'SArrv' => 'Arrived',
|
|
'SRejc' => 'Rejected',
|
|
'SRcvd' => 'Received',
|
|
'SPAna' => 'Pre-analytical',
|
|
'SPAF' => 'Pre-analytical failed',
|
|
'STA' => 'To be analyze',
|
|
'SAFld' => 'Analytical failed',
|
|
'SAna' => 'Analytical',
|
|
'STS' => 'To be stored',
|
|
'SSFld' => 'Store failed',
|
|
'SStrd' => 'Stored',
|
|
'SExp' => 'Expired',
|
|
'STD' => 'To be destroyed',
|
|
'SDFld' => 'Failed to destroy',
|
|
'SDstd' => 'Destroyed'
|
|
];
|
|
|
|
// VSetID 21: Specimen Condition
|
|
const SPECIMEN_CONDITION = [
|
|
'HEM' => 'Hemolyzed',
|
|
'ITC' => 'Icteric',
|
|
'LIP' => 'Lipemic',
|
|
'CFU' => 'Centrifuged',
|
|
'ROOM' => 'Room temperature',
|
|
'COOL' => 'Cool',
|
|
'FROZ' => 'Frozen',
|
|
'CLOT' => 'Clotted',
|
|
'AUT' => 'Autolyzed',
|
|
'CON' => 'Contaminated',
|
|
'LIVE' => 'Live'
|
|
];
|
|
|
|
// VSetID 22: Specimen Role
|
|
const SPECIMEN_ROLE = [
|
|
'P' => 'Patient',
|
|
'B' => 'Blind Sample',
|
|
'Q' => 'Control specimen',
|
|
'E' => 'Electronic QC',
|
|
'F' => 'Filler Organization Proficiency',
|
|
'O' => 'Operator Proficiency',
|
|
'C' => 'Calibrator',
|
|
'R' => 'Replicate',
|
|
'V' => 'Verifying Calibrator'
|
|
];
|
|
|
|
// VSetID 23: Collection Method
|
|
const COLLECTION_METHOD = [
|
|
'pcntr' => 'Puncture',
|
|
'fprk' => 'Finger-prick sampling',
|
|
'ucct' => 'Urine specimen collection, clean catch',
|
|
'utcl' => 'Timed urine collection',
|
|
'ucth' => 'Urine specimen collection, catheterized',
|
|
'scgh' => 'Collection of coughed sputum',
|
|
'bpsy' => 'Biopsy',
|
|
'aspn' => 'Aspiration',
|
|
'excs' => 'Excision',
|
|
'scrp' => 'Scraping'
|
|
];
|
|
|
|
// VSetID 24: Body Site
|
|
const BODY_SITE = [
|
|
'LA' => 'Left Arm',
|
|
'RA' => 'Right Arm',
|
|
'LF' => 'Left Foot',
|
|
'RF' => 'Right Foot'
|
|
];
|
|
|
|
// VSetID 25: Container Size
|
|
const CONTAINER_SIZE = [
|
|
'5ml' => '5 mL',
|
|
'7ml' => '7 mL',
|
|
'10ml' => '10 mL',
|
|
'1l' => '1 L'
|
|
];
|
|
|
|
// VSetID 26: Fasting Status
|
|
const FASTING_STATUS = [
|
|
'F' => 'Fasting',
|
|
'NF' => 'Not Fasting',
|
|
'NG' => 'Not Given'
|
|
];
|
|
|
|
// VSetID 27: Test Type
|
|
const TEST_TYPE = [
|
|
'TEST' => 'Test',
|
|
'PARAM' => 'Parameter',
|
|
'CALC' => 'Calculated Test',
|
|
'GROUP' => 'Group Test',
|
|
'TITLE' => 'Title'
|
|
];
|
|
|
|
// VSetID 28: Result Unit
|
|
const RESULT_UNIT = [
|
|
'g/dL' => 'g/dL',
|
|
'g/L' => 'g/L',
|
|
'mg/dL' => 'mg/dL',
|
|
'mg/L' => 'mg/L',
|
|
'L/L' => 'L/L',
|
|
'x106/mL' => 'x106/mL',
|
|
'x1012/L' => 'x1012/L',
|
|
'fL' => 'fL',
|
|
'pg' => 'pg',
|
|
'x109/L' => 'x109/L'
|
|
];
|
|
|
|
// VSetID 29: Formula Language
|
|
const FORMULA_LANGUAGE = [
|
|
'Phyton' => 'Phyton',
|
|
'CQL' => 'Clinical Quality Language',
|
|
'FHIRP' => 'FHIRPath',
|
|
'SQL' => 'SQL'
|
|
];
|
|
|
|
// VSetID 30: Race (Ethnicity)
|
|
const RACE = [
|
|
'JAWA' => 'Jawa',
|
|
'SUNDA' => 'Sunda',
|
|
'BATAK' => 'Batak',
|
|
'SULOR' => 'Suku asal Sulawesi lainnya',
|
|
'MDRA' => 'Madura',
|
|
'BTWI' => 'Betawi',
|
|
'MNG' => 'Minangkabau',
|
|
'BUGIS' => 'Bugis',
|
|
'MLYU' => 'Melayu',
|
|
'SUMSL' => 'Suku asal Sumatera Selatan',
|
|
'BTNOR' => 'Suku asal Banten',
|
|
'NTTOR' => 'Suku asal Nusa Tenggara Timur',
|
|
'BNJAR' => 'Banjar',
|
|
'ACEH' => 'Aceh',
|
|
'BALI' => 'Bali',
|
|
'SASAK' => 'Sasak',
|
|
'DAYAK' => 'Dayak',
|
|
'TNGHA' => 'Tionghoa',
|
|
'PPAOR' => 'Suku asal Papua',
|
|
'MKSSR' => 'Makassar',
|
|
'SUMOR' => 'Suku asal Sumatera lainnya',
|
|
'MLKOR' => 'Suku asal Maluku',
|
|
'KLMOR' => 'Suku asal Kalimantan lainnya',
|
|
'CRBON' => 'Cirebon',
|
|
'JBIOR' => 'Suku asal Jambi',
|
|
'LPGOR' => 'Suku Lampung',
|
|
'NTBOR' => 'Suku asal Nusa Tenggara Barat lainnya',
|
|
'GRTLO' => 'Gorontalo',
|
|
'MNHSA' => 'Minahasa',
|
|
'NIAS' => 'Nias',
|
|
'FORGN' => 'Asing/luar negeri'
|
|
];
|
|
|
|
// VSetID 31: Religion
|
|
const RELIGION = [
|
|
'ISLAM' => 'Islam',
|
|
'KRSTN' => 'Kristen',
|
|
'KTLIK' => 'Katolik',
|
|
'HINDU' => 'Hindu',
|
|
'BUDHA' => 'Budha',
|
|
'KHCU' => 'Khong Hu Cu',
|
|
'OTHER' => 'Lainnya'
|
|
];
|
|
|
|
// VSetID 32: Ethnic
|
|
const ETHNIC = [
|
|
'PPMLN' => 'Papua Melanezoid',
|
|
'NGRID' => 'Negroid',
|
|
'WDOID' => 'Weddoid',
|
|
'MMPM' => 'Melayu Mongoloid_Proto Melayu',
|
|
'MMDM' => 'Melayu Mongoloid_Deutro Melayu',
|
|
'TNGHA' => 'Tionghoa',
|
|
'INDIA' => 'India',
|
|
'ARAB' => 'Arab'
|
|
];
|
|
|
|
// VSetID 33: Country (ISO 2-letter codes - ISO 3166-1 alpha-2)
|
|
const COUNTRY = null; // Loaded from external file
|
|
|
|
/**
|
|
* Get COUNTRY data from external file (lazy load)
|
|
*/
|
|
private static function loadCountryData(): array {
|
|
$file = APPPATH . 'Libraries/Data/Countries.php';
|
|
if (is_file($file)) {
|
|
return require $file;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Get formatted country list
|
|
*/
|
|
public static function getCountry(): array {
|
|
return self::format(self::loadCountryData());
|
|
}
|
|
|
|
// VSetID 34: Container Cap Color
|
|
const CONTAINER_CAP_COLOR = [
|
|
'PRPL' => 'Purple',
|
|
'RED' => 'Red',
|
|
'YLLW' => 'Yellow',
|
|
'GRN' => 'Green',
|
|
'PINK' => 'Pink',
|
|
'LBLU' => 'Light Blue',
|
|
'RBLU' => 'Royal Blue',
|
|
'GRAY' => 'Gray'
|
|
];
|
|
|
|
// VSetID 35: Test Activity
|
|
const TEST_ACTIVITY = [
|
|
'ORD' => 'Order',
|
|
'ANA' => 'Analyse',
|
|
'VER' => 'Result Verification/Technical Validation',
|
|
'REV' => 'Clinical Review/Clinical Validation',
|
|
'REP' => 'Reporting'
|
|
];
|
|
|
|
// VSetID 36: ADT Event
|
|
const ADT_EVENT = [
|
|
'A01' => 'Admit',
|
|
'A02' => 'Transfer',
|
|
'A03' => 'Discharge',
|
|
'A04' => 'Register',
|
|
'A08' => 'Update patient information',
|
|
'A11' => 'Cancel admit',
|
|
'A12' => 'Cancel transfer',
|
|
'A13' => 'Cancel discharge',
|
|
'A23' => 'Delete patient record',
|
|
'A24' => 'Link patient information',
|
|
'A37' => 'Unlink patient information',
|
|
'A54' => 'Change attending doctor',
|
|
'A61' => 'Change consulting doctor'
|
|
];
|
|
|
|
// VSetID 37: Site Type
|
|
const SITE_TYPE = [
|
|
'GH' => 'Government Hospital',
|
|
'PH' => 'Private Hospital',
|
|
'GHL' => 'Government Hospital Lab',
|
|
'PHL' => 'Private Hospital Lab',
|
|
'GL' => 'Government Lab',
|
|
'PL' => 'Private Lab'
|
|
];
|
|
|
|
// VSetID 38: Site Class
|
|
const SITE_CLASS = [
|
|
'A' => 'Kelas A',
|
|
'B' => 'Kelas B',
|
|
'C' => 'Kelas C',
|
|
'D' => 'Kelas D',
|
|
'Utm' => 'Utama',
|
|
'Ptm' => 'Pratama'
|
|
];
|
|
|
|
// VSetID 39: Entity Type
|
|
const ENTITY_TYPE = [
|
|
'HIS' => 'HIS',
|
|
'SITE' => 'Site',
|
|
'WST' => 'Workstation',
|
|
'INST' => 'Equipment/Instrument'
|
|
];
|
|
|
|
// VSetID 40: Area Class
|
|
const AREA_CLASS = [
|
|
'PROP' => 'Propinsi',
|
|
'KAB' => 'Kabupaten',
|
|
'KOTA' => 'Kota'
|
|
];
|
|
|
|
// VSetID 41: Math Sign
|
|
const MATH_SIGN = [
|
|
'=' => 'Equal',
|
|
'<' => 'Less than',
|
|
'>' => 'Greater than',
|
|
'<=' => 'Less than or equal to',
|
|
'>=' => 'Greater than or equal to'
|
|
];
|
|
|
|
// VSetID 42: VCategory
|
|
const V_CATEGORY = [
|
|
'0' => 'System',
|
|
'1' => 'User-defined'
|
|
];
|
|
|
|
// VSetID 43: Result Type
|
|
const RESULT_TYPE = [
|
|
'NMRIC' => 'Numeric',
|
|
'RANGE' => 'Range',
|
|
'TEXT' => 'Text',
|
|
'VSET' => 'Value set'
|
|
];
|
|
|
|
// VSetID 44: Reference Type
|
|
const REFERENCE_TYPE = [
|
|
'NMRC' => 'Numeric',
|
|
'TEXT' => 'Text'
|
|
];
|
|
|
|
// VSetID 45: Range Type
|
|
const RANGE_TYPE = [
|
|
'REF' => 'Reference Range',
|
|
'CRTC' => 'Critical Range',
|
|
'VAL' => 'Validation Range',
|
|
'RERUN' => 'Rerun Range'
|
|
];
|
|
|
|
// VSetID 46: Numeric Reference Type
|
|
const NUMERIC_REF_TYPE = [
|
|
'RANGE' => 'Range',
|
|
'THOLD' => 'Threshold'
|
|
];
|
|
|
|
// VSetID 47: Text Reference Type
|
|
const TEXT_REF_TYPE = [
|
|
'VSET' => 'Value Set',
|
|
'TEXT' => 'Text'
|
|
];
|
|
|
|
// Convenience constants (aliases for common use cases)
|
|
const PRIORITY = self::ORDER_PRIORITY;
|
|
const TEST_STATUS = [
|
|
'PENDING' => 'Waiting for Results',
|
|
'IN_PROCESS' => 'Analyzing',
|
|
'VERIFIED' => 'Verified & Signed',
|
|
'REJECTED' => 'Sample Rejected'
|
|
];
|
|
const REQUEST_STATUS = self::SPECIMEN_STATUS;
|
|
const RESULT_STATUS = [
|
|
'PRELIMINARY' => 'Preliminary',
|
|
'FINAL' => 'Final',
|
|
'CORRECTED' => 'Corrected',
|
|
'CANCELLED' => 'Cancelled'
|
|
];
|
|
|
|
/**
|
|
* Get all lookups formatted for frontend
|
|
* @return array
|
|
*/
|
|
public static function getAll(): array {
|
|
return [
|
|
'ws_type' => self::format(self::WS_TYPE),
|
|
'enable_disable' => self::format(self::ENABLE_DISABLE),
|
|
'gender' => self::format(self::GENDER),
|
|
'marital_status' => self::format(self::MARITAL_STATUS),
|
|
'death_indicator' => self::format(self::DEATH_INDICATOR),
|
|
'identifier_type' => self::format(self::IDENTIFIER_TYPE),
|
|
'operation' => self::format(self::OPERATION),
|
|
'did_type' => self::format(self::DID_TYPE),
|
|
'requested_entity' => self::format(self::REQUESTED_ENTITY),
|
|
'order_priority' => self::format(self::ORDER_PRIORITY),
|
|
'order_status' => self::format(self::ORDER_STATUS),
|
|
'location_type' => self::format(self::LOCATION_TYPE),
|
|
'additive' => self::format(self::ADDITIVE),
|
|
'container_class' => self::format(self::CONTAINER_CLASS),
|
|
'specimen_type' => self::format(self::SPECIMEN_TYPE),
|
|
'unit' => self::format(self::UNIT),
|
|
'generate_by' => self::format(self::GENERATE_BY),
|
|
'specimen_activity' => self::format(self::SPECIMEN_ACTIVITY),
|
|
'activity_result' => self::format(self::ACTIVITY_RESULT),
|
|
'specimen_status' => self::format(self::SPECIMEN_STATUS),
|
|
'specimen_condition' => self::format(self::SPECIMEN_CONDITION),
|
|
'specimen_role' => self::format(self::SPECIMEN_ROLE),
|
|
'collection_method' => self::format(self::COLLECTION_METHOD),
|
|
'body_site' => self::format(self::BODY_SITE),
|
|
'container_size' => self::format(self::CONTAINER_SIZE),
|
|
'fasting_status' => self::format(self::FASTING_STATUS),
|
|
'test_type' => self::format(self::TEST_TYPE),
|
|
'result_unit' => self::format(self::RESULT_UNIT),
|
|
'formula_language' => self::format(self::FORMULA_LANGUAGE),
|
|
'race' => self::format(self::RACE),
|
|
'religion' => self::format(self::RELIGION),
|
|
'ethnic' => self::format(self::ETHNIC),
|
|
'country' => self::getCountry(),
|
|
'container_cap_color' => self::format(self::CONTAINER_CAP_COLOR),
|
|
'test_activity' => self::format(self::TEST_ACTIVITY),
|
|
'adt_event' => self::format(self::ADT_EVENT),
|
|
'site_type' => self::format(self::SITE_TYPE),
|
|
'site_class' => self::format(self::SITE_CLASS),
|
|
'entity_type' => self::format(self::ENTITY_TYPE),
|
|
'area_class' => self::format(self::AREA_CLASS),
|
|
'math_sign' => self::format(self::MATH_SIGN),
|
|
'v_category' => self::format(self::V_CATEGORY),
|
|
'result_type' => self::format(self::RESULT_TYPE),
|
|
'reference_type' => self::format(self::REFERENCE_TYPE),
|
|
'range_type' => self::format(self::RANGE_TYPE),
|
|
'numeric_ref_type' => self::format(self::NUMERIC_REF_TYPE),
|
|
'text_ref_type' => self::format(self::TEXT_REF_TYPE)
|
|
];
|
|
}
|
|
|
|
|
|
/**
|
|
* Format associative array as [{value: 'KEY', label: 'Label'}, ...]
|
|
*/
|
|
private static function format(array $array): array {
|
|
$result = [];
|
|
foreach ($array as $key => $label) {
|
|
$result[] = ['value' => (string) $key, 'label' => (string) $label];
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Get single lookup by constant name (case-insensitive)
|
|
* @param string $name Constant name (e.g., 'gender', 'PRIORITY')
|
|
* @return array|null
|
|
*/
|
|
public static function get(string $name): ?array {
|
|
$const = strtoupper($name);
|
|
// Special case for COUNTRY (loaded from external file)
|
|
if ($const === 'COUNTRY') {
|
|
return self::getCountry();
|
|
}
|
|
if (defined("self::$const")) {
|
|
return self::format(constant("self::$const"));
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get raw constant array (not formatted)
|
|
* @param string $name
|
|
* @return array|null
|
|
*/
|
|
public static function getRaw(string $name): ?array {
|
|
$const = strtoupper($name);
|
|
// Special case for COUNTRY (loaded from external file)
|
|
if ($const === 'COUNTRY') {
|
|
return self::loadCountryData();
|
|
}
|
|
if (defined("self::$const")) {
|
|
return constant("self::$const");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Get label by key from a lookup
|
|
* @param string $lookup Lookup name
|
|
* @param string $key Key to find
|
|
* @return string|null
|
|
*/
|
|
public static function getLabel(string $lookup, string $key): ?string {
|
|
$raw = self::getRaw($lookup);
|
|
return $raw[$key] ?? null;
|
|
}
|
|
}
|