updates to make oauth2/api compatible with php8 (#4069)
[openemr.git] / src / Services / FacilityService.php
blob2af89aabe9daaa75f6d32f99633fd3395fb7f89d
1 <?php
3 /**
4 * FacilityService
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Matthew Vita <matthewvita48@gmail.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Sherwin Gaddis <sherwingaddis@gmail.com>
11 * @author Jerry Padgett <sjpadgett@gmail.com>
12 * @copyright Copyright (c) 2018 Matthew Vita <matthewvita48@gmail.com>
13 * @copyright Copyright (c) 2018 Brady Miller <brady.g.miller@gmail.com>
14 * @copyright Copyright (c) 2020 Jerry Padgett <sjpadgett@gmail.com>
15 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
18 namespace OpenEMR\Services;
20 use OpenEMR\Common\Uuid\UuidRegistry;
21 use OpenEMR\Validators\FacilityValidator;
22 use OpenEMR\Validators\ProcessingResult;
23 use OpenEMR\Events\Facility\FacilityCreatedEvent;
24 use OpenEMR\Events\Facility\FacilityUpdatedEvent;
25 use Particle\Validator\Validator;
27 class FacilityService extends BaseService
29 private $facilityValidator;
30 private $uuidRegistry;
31 private const FACILITY_TABLE = "facility";
33 /**
34 * Default constructor.
36 public function __construct()
38 parent::__construct(self::FACILITY_TABLE);
39 $this->uuidRegistry = new UuidRegistry(['table_name' => self::FACILITY_TABLE]);
40 $this->uuidRegistry->createMissingUuids();
41 $this->facilityValidator = new FacilityValidator();
44 public function validate($facility)
46 $validator = new Validator();
48 $validator->required('name')->lengthBetween(2, 255);
49 $validator->required('phone')->lengthBetween(3, 30);
50 $validator->required('city')->lengthBetween(2, 255);
51 $validator->required('state')->lengthBetween(2, 50);
52 $validator->required('street')->lengthBetween(2, 255);
53 $validator->required('postal_code')->lengthBetween(2, 11);
54 $validator->required('email')->email();
55 $validator->required('fax')->lengthBetween(3, 30);
56 $validator->optional('country_code')->lengthBetween(2, 30);
57 $validator->optional('federal_ein')->lengthBetween(2, 15);
58 $validator->optional('website')->url();
59 $validator->optional('color')->lengthBetween(4, 7);
60 $validator->optional('service_location')->numeric();
61 $validator->optional('billing_location')->numeric();
62 $validator->optional('accepts_assignment')->numeric();
63 $validator->optional('pos_code')->numeric();
64 $validator->optional('domain_identifier')->lengthBetween(2, 60);
65 $validator->optional('attn')->lengthBetween(2, 65);
66 $validator->optional('tax_id_type')->lengthBetween(2, 31);
67 $validator->optional('primary_business_entity')->numeric();
68 $validator->optional('facility_npi')->lengthBetween(2, 15);
69 $validator->optional('facility_code')->lengthBetween(2, 31);
70 $validator->optional('facility_taxonomy')->lengthBetween(2, 15);
71 $validator->optional('iban')->lengthBetween(2, 34);
73 return $validator->validate($facility);
76 public function getAllFacility()
78 return $this->get(array("order" => "ORDER BY FAC.name ASC"));
81 public function getPrimaryBusinessEntity($options = null)
83 if (!empty($options) && !empty($options["useLegacyImplementation"])) {
84 return $this->getPrimaryBusinessEntityLegacy();
87 $args = array(
88 "where" => "WHERE FAC.primary_business_entity = 1",
89 "data" => null,
90 "limit" => 1
93 if (!empty($options) && !empty($options["excludedId"])) {
94 $args["where"] .= " AND FAC.id != ?";
95 $args["data"] = $options["excludedId"];
96 return $this->get($args);
99 return $this->get($args);
102 public function getAllServiceLocations($options = null)
104 $args = array(
105 "where" => null,
106 "order" => "ORDER BY FAC.name ASC"
109 if (!empty($options) && !empty($options["orderField"])) {
110 $args["order"] = "ORDER BY FAC." . escape_sql_column_name($options["orderField"], array("facility")) . " ASC";
113 $args["where"] = "WHERE FAC.service_location = 1";
115 return $this->get($args);
118 public function getPrimaryBillingLocation()
120 return $this->get(array(
121 "order" => "ORDER BY FAC.billing_location DESC, FAC.id DESC",
122 "limit" => 1
126 public function getAllBillingLocations()
128 return $this->get(array(
129 "where" => "WHERE FAC.billing_location = 1",
130 "order" => "ORDER BY FAC.id ASC"
134 public function getById($id)
136 return $this->get(array(
137 "where" => "WHERE FAC.id = ?",
138 "data" => array($id),
139 "limit" => 1
143 public function getFacilityForUser($userId)
145 return $this->get(array(
146 "where" => "WHERE USER.id = ?",
147 "data" => array($userId),
148 "join" => "JOIN users USER ON FAC.id = USER.facility_id",
149 "limit" => 1
153 public function getFacilityForUserFormatted($userId)
155 $facility = $this->getFacilityForUser($userId);
157 if (!empty($facility)) {
158 $formatted = "";
159 $formatted .= $facility["name"];
160 $formatted .= "\n";
161 $formatted .= $facility["street"];
162 $formatted .= "\n";
163 $formatted .= $facility["city"];
164 $formatted .= "\n";
165 $formatted .= $facility["state"];
166 $formatted .= "\n";
167 $formatted .= $facility["postal_code"];
169 return array("facility_address" => $formatted);
172 return array("facility_address" => "");
175 public function getFacilityForEncounter($encounterId)
177 return $this->get(array(
178 "where" => "WHERE ENC.encounter = ?",
179 "data" => array($encounterId),
180 "join" => "JOIN form_encounter ENC ON FAC.id = ENC.facility_id",
181 "limit" => 1
185 public function updateFacility($data)
187 $dataBeforeUpdate = $this->getById($data['id']);
188 $query = $this->buildUpdateColumns($data);
189 $sql = " UPDATE facility SET ";
190 $sql .= $query['set'];
191 $sql .= " WHERE id = ?";
192 array_push($query['bind'], $data['id']);
193 $result = sqlStatement(
194 $sql,
195 $query['bind']
198 $facilityUpdatedEvent = new FacilityUpdatedEvent($dataBeforeUpdate, $data);
199 $GLOBALS["kernel"]->getEventDispatcher()->dispatch(FacilityUpdatedEvent::EVENT_HANDLE, $facilityUpdatedEvent, 10);
201 return $result;
204 public function insertFacility($data)
206 $query = $this->buildInsertColumns($data);
207 $sql = " INSERT INTO facility SET ";
208 $sql .= $query['set'];
209 $facilityId = sqlInsert(
210 $sql,
211 $query['bind']
214 $facilityCreatedEvent = new FacilityCreatedEvent(array_merge($data, ['id' => $facilityId]));
215 $GLOBALS["kernel"]->getEventDispatcher()->dispatch(FacilityCreatedEvent::EVENT_HANDLE, $facilityCreatedEvent, 10);
217 return $facilityId;
220 public function updateUsersFacility($facility_name, $facility_id)
222 $sql = " UPDATE users SET";
223 $sql .= " facility=?";
224 $sql .= " WHERE facility_id=?";
226 return sqlStatement($sql, array($facility_name, $facility_id));
230 * Shared getter for the various specific facility getters.
232 * @param $map - Query information.
233 * @return array of associative arrays | one associative array.
235 private function get($map)
237 $sql = " SELECT FAC.id,";
238 $sql .= " FAC.uuid,";
239 $sql .= " FAC.name,";
240 $sql .= " FAC.phone,";
241 $sql .= " FAC.fax,";
242 $sql .= " FAC.street,";
243 $sql .= " FAC.city,";
244 $sql .= " FAC.state,";
245 $sql .= " FAC.postal_code,";
246 $sql .= " FAC.country_code,";
247 $sql .= " FAC.federal_ein,";
248 $sql .= " FAC.website,";
249 $sql .= " FAC.email,";
250 $sql .= " FAC.service_location,";
251 $sql .= " FAC.billing_location,";
252 $sql .= " FAC.accepts_assignment,";
253 $sql .= " FAC.pos_code,";
254 $sql .= " FAC.x12_sender_id,";
255 $sql .= " FAC.attn,";
256 $sql .= " FAC.domain_identifier,";
257 $sql .= " FAC.facility_npi,";
258 $sql .= " FAC.facility_taxonomy,";
259 $sql .= " FAC.tax_id_type,";
260 $sql .= " FAC.color,";
261 $sql .= " FAC.primary_business_entity,";
262 $sql .= " FAC.facility_code,";
263 $sql .= " FAC.extra_validation,";
264 $sql .= " FAC.mail_street,";
265 $sql .= " FAC.mail_street2,";
266 $sql .= " FAC.mail_city,";
267 $sql .= " FAC.mail_state,";
268 $sql .= " FAC.mail_zip,";
269 $sql .= " FAC.oid,";
270 $sql .= " FAC.iban,";
271 $sql .= " FAC.info";
272 $sql .= " FROM facility FAC";
274 return self::selectHelper($sql, $map);
277 private function getPrimaryBusinessEntityLegacy()
279 return $this->get(array(
280 "order" => "ORDER BY FAC.billing_location DESC, FAC.accepts_assignment DESC, FAC.id ASC",
281 "limit" => 1
286 * Returns a list of facilities matching optional search criteria.
287 * Search criteria is conveyed by array where key = field/column name, value = field value.
288 * If no search criteria is provided, all records are returned.
290 * @param $search search array parameters
291 * @param $isAndCondition specifies if AND condition is used for multiple criteria. Defaults to true.
292 * @return ProcessingResult which contains validation messages, internal error messages, and the data
293 * payload.
295 public function getAll($search = array(), $isAndCondition = true)
297 $processingResult = new ProcessingResult();
299 // Validating and Converting _id to UUID byte
300 if (isset($search['uuid'])) {
301 $isValid = $this->facilityValidator->validateId(
302 'uuid',
303 self::FACILITY_TABLE,
304 $search['uuid'],
305 true
307 if ($isValid != true) {
308 return $isValid;
310 $search['uuid'] = UuidRegistry::uuidToBytes($search['uuid']);
312 $additionalSql = array();
313 if (!empty($search)) {
314 $additionalSql['where'] = ' WHERE ';
315 $additionalSql["data"] = array();
316 $whereClauses = array();
317 foreach ($search as $fieldName => $fieldValue) {
318 // equality match
319 array_push($whereClauses, $fieldName . ' = ?');
320 array_push($additionalSql["data"], $fieldValue);
322 $sqlCondition = ($isAndCondition == true) ? 'AND' : 'OR';
323 $additionalSql['where'] .= implode(' ' . $sqlCondition . ' ', $whereClauses);
325 $statementResults = $this->get($additionalSql);
326 if ($statementResults) {
327 foreach ($statementResults as $row) {
328 $row['uuid'] = UuidRegistry::uuidToString($row['uuid']);
329 $processingResult->addData($row);
333 return $processingResult;
337 * Returns a single facility record by facility uuid.
338 * @param $uuid - The facility uuid identifier in string format.
339 * @return ProcessingResult which contains validation messages, internal error messages, and the data
340 * payload.
342 public function getOne($uuid)
344 $processingResult = new ProcessingResult();
345 $isValid = $this->facilityValidator->validateId('uuid', self::FACILITY_TABLE, $uuid, true);
346 if ($isValid !== true) {
347 return $isValid;
349 $uuidBytes = UuidRegistry::uuidToBytes($uuid);
350 $sqlResult = $this->get(array(
351 "where" => "WHERE FAC.uuid = ?",
352 "data" => array($uuidBytes),
353 "limit" => 1
356 if ($sqlResult) {
357 $sqlResult['uuid'] = UuidRegistry::uuidToString($sqlResult['uuid']);
358 $processingResult->addData($sqlResult);
359 } else {
360 $processingResult->addInternalError("error processing SQL Insert");
363 return $processingResult;
367 * Inserts a new facility record.
369 * @param $data The facility fields (array) to insert.
370 * @return ProcessingResult which contains validation messages, internal error messages, and the data
371 * payload.
373 public function insert($data)
375 $processingResult = $this->facilityValidator->validate(
376 $data,
377 FacilityValidator::DATABASE_INSERT_CONTEXT
380 if (!$processingResult->isValid()) {
381 return $processingResult;
384 $data['uuid'] = (new UuidRegistry(['table_name' => self::FACILITY_TABLE]))->createUuid();
386 $query = $this->buildInsertColumns($data);
387 $sql = " INSERT INTO " . self::FACILITY_TABLE . " SET ";
388 $sql .= $query['set'];
390 $results = sqlInsert(
391 $sql,
392 $query['bind']
395 if ($results) {
396 $processingResult->addData(array(
397 'id' => $results,
398 'uuid' => UuidRegistry::uuidToString($data['uuid'])
400 } else {
401 $processingResult->addInternalError("error processing SQL Insert");
404 return $processingResult;
408 * Updates an existing facility record.
410 * @param $uuid - The facility uuid identifier in string format used for update.
411 * @param $data - The updated facility data fields
412 * @return ProcessingResult which contains validation messages, internal error messages, and the data
413 * payload.
415 public function update($uuid, $data)
417 if (empty($data)) {
418 $processingResult = new ProcessingResult();
419 $processingResult->setValidationMessages("Invalid Data");
420 return $processingResult;
422 $data["uuid"] = $uuid;
423 $processingResult = $this->facilityValidator->validate(
424 $data,
425 FacilityValidator::DATABASE_UPDATE_CONTEXT
427 if (!$processingResult->isValid()) {
428 return $processingResult;
431 $query = $this->buildUpdateColumns($data);
432 $sql = " UPDATE " . self::FACILITY_TABLE . " SET ";
433 $sql .= $query['set'];
434 $sql .= " WHERE `uuid` = ?";
436 $uuidBinary = UuidRegistry::uuidToBytes($uuid);
437 array_push($query['bind'], $uuidBinary);
438 $sqlResult = sqlStatement($sql, $query['bind']);
440 if (!$sqlResult) {
441 $processingResult->addErrorMessage("error processing SQL Update");
442 } else {
443 $processingResult = $this->getOne($uuid);
445 return $processingResult;