You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

271 lines
8.7 KiB

<?php
namespace OpenEMR\Tests\Fixtures;
use OpenEMR\Common\Uuid\UuidRegistry;
use OpenEMR\Common\Database\QueryUtils;
use Ramsey\Uuid\Uuid;
/**
* Provides OpenEMR Fixtures/Sample Records to test cases as Objects or Database Records.
*
* The FixtureManager generates sample records from JSON files located within the Fixture namespace.
* To provide support for additional record types:
* - Add a JSON datafile to the Fixture namespace containing the sample records.
* - Add public methods to get, install, and remove fixture records.
* - The "patient" related methods provide clear working examples.
*
* @package OpenEMR
* @link http://www.open-emr.org
* @author Dixon Whitmire <dixonwh@gmail.com>
* @copyright Copyright (c) 2020 Dixon Whitmire <dixonwh@gmail.com>
* @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
*/
class FixtureManager
{
// use a prefix so we can easily remove fixtures
const PATIENT_FIXTURE_PUBPID_PREFIX = "test-fixture";
private $patientFixtures;
private $fhirPatientFixtures;
private $addressFixtures;
private $contactFixtures;
private $contactAddressFixtures;
/**
* @var
*/
private $fhirAllergyIntoleranceFixtures;
public function __construct()
{
$this->addressFixtures = $this->loadJsonFile("addresses.json");
$this->contactAddressFixtures = $this->loadJsonFile("contact-addresses.json");
$this->contactFixtures = $this->loadJsonFile("contacts.json");
$this->patientFixtures = $this->loadJsonFile("patients.json");
$this->fhirPatientFixtures = $this->loadJsonFile("FHIR/patients.json");
}
/**
* Loads a JSON fixture from a file within the Fixture namespace, returning the data as an array of records.
* @param $fileName The file name to load.
* @return array of records.
*/
private function loadJsonFile($fileName)
{
$filePath = dirname(__FILE__) . "/" . $fileName;
$jsonData = file_get_contents($filePath);
$parsedRecords = json_decode($jsonData, true);
return $parsedRecords;
}
/**
*
* This will return a recorded uuid (recorded in uuid_registry)
*
* @param $tableName The target OpenEMR DB table name.
* @return uuid.
*/
private function getUuid($tableName)
{
return (new UuidRegistry(['table_name' => $tableName]))->createUuid();
}
/**
* @return the next available patient pid/identifier.
*/
private function getNextPid()
{
$pidQuery = "SELECT IFNULL(MAX(pid), 0) + 1 FROM patient_data";
$pidResult = sqlQueryNoLog($pidQuery);
$pidValue = intval(array_values($pidResult)[0]);
return $pidValue;
}
/**
* Installs fixtures into the OpenEMR DB.
*
* @param $tableName The target OpenEMR DB table name.
* @param $fixtures Array of fixture objects to install.
* @return the number of fixtures installed.
*/
private function installFixtures($tableName, $fixtures)
{
$insertCount = 0;
$sqlInsert = "INSERT INTO " . escape_table_name($tableName) . " SET ";
foreach ($fixtures as $index => $fixture) {
$sqlColumnValues = "";
$sqlBinds = array();
foreach ($fixture as $field => $fieldValue) {
// not sure I like table specific comparisons here...
if ($tableName == 'lists' && $field == 'pid') {
$sqlColumnValues .= "pid = (SELECT pid FROM patient_data WHERE pubpid=? LIMIT 1) ,";
} else {
$sqlColumnValues .= $field . " = ?, ";
}
// if ($field === 'uuid') {
// $fieldValue = UuidRegistry::uuidToBytes($fieldValue);
// }
array_push($sqlBinds, $fieldValue);
}
if ($tableName == "patient_data") {
// add pid
$sqlColumnValues .= 'pid = ? ,';
$nextPidValue = $this->getNextPid();
array_push($sqlBinds, $nextPidValue);
// add uuid
$sqlColumnValues .= '`uuid` = ?';
$uuidPatient = $this->getUuid("patient_data");
array_push($sqlBinds, $uuidPatient);
}
$sqlColumnValues = rtrim($sqlColumnValues, " ,");
$isInserted = QueryUtils::sqlInsert($sqlInsert . $sqlColumnValues, $sqlBinds);
if ($isInserted) {
$insertCount += 1;
}
}
return $insertCount;
}
/**
* @return array of fhir patient fixtures.
*/
public function getFhirPatientFixtures()
{
return $this->fhirPatientFixtures;
}
/**
* @return single/random fhir patient fixture
*/
public function getSingleFhirPatientFixture()
{
return $this->getSingleEntry($this->fhirPatientFixtures);
}
/**
* @return array of patient fixtures.
*/
public function getPatientFixtures()
{
return $this->patientFixtures;
}
public function getAllergyIntoleranceFixtures()
{
if (empty($this->fhirAllergyIntoleranceFixtures)) {
$this->fhirAllergyIntoleranceFixtures = $this->loadJsonFile("allergy-intolerance.json");
}
return $this->fhirAllergyIntoleranceFixtures;
}
/**
* @return random single entry from an array.
*/
private function getSingleEntry($array)
{
$randomIndex = array_rand($array, 1);
return $array[$randomIndex];
}
/**
* @return a random patient fixture.
*/
public function getSinglePatientFixture()
{
return $this->getSingleEntry($this->patientFixtures);
}
public function getSinglePatientFixtureWithAddressInformation()
{
$entry = $this->getSingleEntry($this->patientFixtures);
$address = $this->getSingleEntry($this->addressFixtures);
$contactAddress = $this->getSingleEntry($this->contactAddressFixtures);
$contactAddress['contact_id'] = hexdec(uniqid()); // just need a random unique id
unset($contactAddress['address_id']);
// now combine our contact address and address for our unique address information
$entry['addresses'] = [
array_merge($address, $contactAddress)
];
return $entry;
}
/**
* Installs Patient Fixtures into the OpenEMR DB.
*/
public function installPatientFixtures()
{
return $this->installFixtures("patient_data", $this->getPatientFixtures());
}
/**
* Installs a single Patient Fixtures into the OpenEMR DB.
* @param $patientFixture - The fixture to install.
* @return count of records inserted.
*/
public function installSinglePatientFixture($patientFixture)
{
return $this->installFixtures("patient_data", array($patientFixture));
}
/**
* Removes Patient Fixtures from the OpenEMR DB.
*/
public function removePatientFixtures()
{
$bindVariable = self::PATIENT_FIXTURE_PUBPID_PREFIX . "%";
// remove the related uuids from uuid_registry
$select = "SELECT `uuid` FROM `patient_data` WHERE `pubpid` LIKE ?";
$sel = sqlStatement($select, [$bindVariable]);
while ($row = sqlFetchArray($sel)) {
sqlQuery("DELETE FROM `uuid_registry` WHERE `table_name` = 'patient_data' AND `uuid` = ?", [$row['uuid']]);
}
// remove the patients
$delete = "DELETE FROM patient_data WHERE pubpid LIKE ?";
sqlStatement($delete, array($bindVariable));
}
public function installAllergyIntoleranceFixtures()
{
$this->installPatientFixtures();
$installed = $this->installFixtures("lists", $this->getAllergyIntoleranceFixtures());
if ($installed < 1) {
throw new \RuntimeException("Failed to install allergy intolerance fixtures");
}
}
public function removeAllergyIntoleranceFixtures()
{
$pubpid = self::PATIENT_FIXTURE_PUBPID_PREFIX . "%";
$pids = QueryUtils::fetchTableColumn(
"SELECT `pid` FROM `patient_data` WHERE `pubpid` LIKE ?",
'pid',
[$pubpid]
);
if (!empty($pids)) {
$count = count($pids) - 1;
$where = "WHERE pid = ? " . str_repeat("OR pid = ? ", $count);
$sqlStatement = "DELETE FROM `lists` " . $where;
QueryUtils::sqlStatementThrowException($sqlStatement, $pids);
}
$this->removePatientFixtures();
}
/**
* Returns an unregistered/unlogged UUID for use in testing fixtures
* @return uuid4 string value
*/
public function getUnregisteredUuid()
{
$uuid4 = Uuid::uuid4();
return $uuid4->toString();
}
}