Openemr fhir device, careplan, goal (#4422)
[openemr.git] / tests / Tests / Fixtures / BaseFixtureManager.php
bloba61096ba8ca07ac347b452d43bbbb2c48b6dca63
1 <?php
3 namespace OpenEMR\Tests\Fixtures;
5 use OpenEMR\Common\Database\QueryUtils;
6 use OpenEMR\Common\Database\SqlQueryException;
7 use OpenEMR\Common\Logging\SystemLogger;
8 use OpenEMR\Common\Uuid\UuidRegistry;
9 use OpenEMR\Services\Search\SearchQueryFragment;
10 use Ramsey\Uuid\Uuid;
12 /**
13 * Provides OpenEMR Fixtures/Sample Records to test cases as Objects or Database Records.
15 * @package OpenEMR
16 * @link http://www.open-emr.org
17 * @author Yash Bothra <yashrajbothra786gmail.com>
18 * @copyright Copyright (c) 2020 Yash Bothra <yashrajbothra786gmail.com>
19 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
21 abstract class BaseFixtureManager
23 // use a prefix so we can easily remove fixtures
24 const FIXTURE_PREFIX = "test-fixture";
26 private $fileName;
27 private $tableName;
28 private $hasInstalledFixtured;
29 private $fixtures;
31 public function __construct($fileName = "", $tableName = "")
33 $this->fileName = $fileName;
34 $this->tableName = $tableName;
35 $this->hasInstalledFixtured = false;
38 protected function getFixturesFromFile()
40 if (empty($this->fixtures)) {
41 $this->fixtures = $this->loadJsonFile($this->fileName);
43 return $this->fixtures;
46 /**
47 * Loads a JSON fixture from a file within the Fixture namespace, returning the data as an array of records.
48 * @param $fileName The file name to load.
49 * @return array of records.
51 protected function loadJsonFile($fileName)
53 $filePath = dirname(__FILE__) . "/" . $fileName;
54 $jsonData = file_get_contents($filePath);
55 $parsedRecords = json_decode($jsonData, true);
56 return $parsedRecords;
59 /**
61 * This will return a recorded uuid (recorded in uuid_registry)
63 * @param $tableName The target OpenEMR DB table name.
64 * @return uuid.
66 protected function getUuid($tableName)
68 return (new UuidRegistry(['table_name' => $tableName]))->createUuid();
71 /**
72 * @return the next available id/identifier in the table.
74 protected function getNextId($tableName, $idField)
76 $idQuery = "SELECT IFNULL(MAX($idField), 0) + 1 FROM $tableName";
77 $idResult = sqlQueryNoLog($idQuery);
78 $idValue = intval(array_values($idResult)[0]);
79 return $idValue;
82 /**
83 * Returns an unregistered/unlogged UUID for use in testing fixtures
84 * @return uuid4 string value
86 public function getUnregisteredUuid()
88 return UuidRegistry::uuidToString((new UuidRegistry(['disable_tracker' => true]))->createUuid());
91 /**
92 * Installs fixtures into the OpenEMR DB.
94 * @param $tableName The target OpenEMR DB table name.
95 * @param $fixtures Array of fixture objects to install.
96 * @return the number of fixtures installed.
98 protected function installFixturesForTable($tableName, $fixtures)
100 $insertCount = 0;
101 $sqlInsert = "INSERT INTO " . escape_table_name($tableName) . " SET ";
103 foreach ($fixtures as $index => $fixture) {
104 $sqlColumnValues = "";
105 $sqlBinds = array();
107 foreach ($fixture as $field => $fieldValue) {
108 if (is_array($fieldValue) && $this->isForeignReference($fieldValue)) {
109 $fragment = $this->getQueryForForeignReference($fieldValue);
110 $sqlColumnValues .= $field . " = " . $fragment->getFragment() . ", ";
111 $sqlBinds = array_merge($sqlBinds, $fragment->getBoundValues());
112 } else if ($this->isFunctionCall($fieldValue)) {
113 $sqlColumnValues .= $field . " = ?, ";
114 $fieldValue = $this->getValueFromFunction($fieldValue);
115 array_push($sqlBinds, $fieldValue);
116 } else {
117 $sqlColumnValues .= $field . " = ?, ";
118 array_push($sqlBinds, $fieldValue);
121 $sqlColumnValues = rtrim($sqlColumnValues, " ,");
122 $isInserted = QueryUtils::sqlInsert($sqlInsert . $sqlColumnValues, $sqlBinds);
123 if ($isInserted) {
124 $insertCount += 1;
127 return $insertCount;
130 public function installFixtures()
132 $fixtures = $this->getFixturesFromFile();
133 $insertCount = $this->installFixturesForTable($this->tableName, $fixtures);
134 $this->hasInstalledFixtured = true;
135 return $insertCount;
138 // we don't have a good way to solve this so we will force all sub classes to implement.
139 public function removeFixtures()
141 // we have no generic way of signifying what the primary key of the table is so we force sub classes
142 // to implement the remove fixture method
143 $this->removeInstalledFixtures();
144 $this->hasInstalledFixtured = false;
147 public function hasInstalledFixtures()
149 return $this->hasInstalledFixtured;
153 * @return a random fixture.
155 public function getSingleFixture()
157 $fixtures = $this->getFixturesFromFile();
158 return $this->getSingleEntry($fixtures);
161 abstract protected function removeInstalledFixtures();
163 private function getValueFromFunction($value)
165 $functionName = strtok($value, "()");
167 // white list our functions here
168 if ($functionName === "uuid") {
169 $table = strtok("(,)");
170 if ($table !== false) {
171 // trim spaces, and quotes
172 $table = trim($table, "'\" \t\n\r\0\x0B");
173 return $this->getUuid($table);
174 } else {
175 throw new \BadMethodCallException("uuid(table_name) function is missing table name");
177 } else if ($functionName === "generateId") {
178 return QueryUtils::generateId();
179 } else {
180 throw new \BadMethodCallException("Function could not be interpreted from fixture: " . $value);
182 return ""; // return empty string
185 private function isFunctionCall($value)
187 return preg_match("/[a-zA-Z]+\(['a-zA-Z_0-9\-]*\)/", $value) === 1;
190 private function isForeignReference(array $reference)
192 return isset($reference['table']) && isset($reference['columnSearch']) && isset($reference['columnSearchValue']) && isset($reference['columnReference']);
195 private function getQueryForForeignReference(array $reference): SearchQueryFragment
197 try {
198 $table_name = escape_table_name($reference['table']);
199 $column = escape_sql_column_name($reference['columnSearch'], [$reference['table']], false, true);
200 $referenceColumn = escape_sql_column_name($reference['columnReference'], [$reference['table']], false, true);
201 $searchValue = $reference['columnSearchValue'];
202 $sql = "( SELECT $referenceColumn FROM $table_name WHERE $column = ? )";
203 } catch (SqlQueryException $exception) {
204 (new SystemLogger())->error("Failed to escape column for foreign key reference ", ['reference' => $reference]);
205 throw $exception;
207 return new SearchQueryFragment($sql, [$reference['columnSearchValue']]);
211 * @return random single entry from an array.
213 protected function getSingleEntry($array)
215 if (empty($array)) {
216 throw new \InvalidArgumentException("cannot get single entry from empty array");
218 $randomIndex = array_rand($array, 1);
219 return $array[$randomIndex];