Fix and refactor contrib form scanned_notes. (#7889)
[openemr.git] / src / FHIR / R4 / PHPFHIRResponseParser.php
blob811131b0ad8f92211164087e8b7ce17e2b118054
1 <?php
3 namespace OpenEMR\FHIR\R4;
5 /*!
6 * This class was generated with the PHPFHIR library (https://github.com/dcarbone/php-fhir) using
7 * class definitions from HL7 FHIR (https://www.hl7.org/fhir/)
9 * Class creation date: June 14th, 2019
11 * PHPFHIR Copyright:
13 * Copyright 2016-2017 Daniel Carbone (daniel.p.carbone@gmail.com)
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
19 * http://www.apache.org/licenses/LICENSE-2.0
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
29 class PHPFHIRResponseParser
31 /**
32 * If response is XML, these arguments will be passed into the \SimpleXMLElement constructor
33 * @see http://php.net/manual/en/libxml.constants.php for a list of options.
34 * @var int
36 public static $sxeArgs = null;
38 /** @var PHPFHIRParserMap */
39 private $_parserMap;
41 /**
42 * Constructor
44 * @param bool $registerAutoloader
46 public function __construct($registerAutoloader = true)
48 if (null === self::$sxeArgs) {
49 self::$sxeArgs = LIBXML_COMPACT | LIBXML_NSCLEAN;
52 if ($registerAutoloader) {
53 self::_registerAutoloader();
56 $this->_parserMap = new PHPFHIRParserMap();
59 /**
60 * @param string $input
61 * @return object Root object type depends on initial query type and parameters
63 public function parse($input)
65 if (!is_string($input)) {
66 throw $this->_createNonStringArgumentException($input);
69 switch (substr($input, 0, 1)) {
70 case '<':
71 return $this->_parseXML($input);
73 case '{':
74 return $this->_parseJson($input);
76 default:
77 throw new \RuntimeException(sprintf(
78 '%s::parse - Unable to determine response type, expected JSON or XML.',
79 get_class($this)
80 ));
84 /**
85 * @param string $input
86 * @return object
88 private function _parseJson($input)
90 $decoded = json_decode($input, true);
92 $lastError = json_last_error();
93 if (JSON_ERROR_NONE === $lastError) {
94 return $this->_parseJsonObject($decoded, $decoded['resourceType']);
97 throw new \DomainException(sprintf(
98 '%s::parse - Error encountered while decoding json input. Error code: %s',
99 get_class($this),
100 $lastError
105 * @param string $input
106 * @return object
108 private function _parseXML($input)
110 libxml_use_internal_errors(true);
111 $sxe = new \SimpleXMLElement($input, self::$sxeArgs);
112 $error = libxml_get_last_error();
113 libxml_use_internal_errors(false);
115 if ($sxe instanceof \SimpleXMLElement) {
116 return $this->_parseXMLNode($sxe, $sxe->getName());
119 throw new \RuntimeException(sprintf(
120 'Unable to parse response: "%s"',
121 ($error ? $error->message : 'Unknown Error')
126 * @param array $jsonEntry
127 * @param string $fhirElementName
128 * @return mixed
130 private function _parseJsonObject($jsonEntry, $fhirElementName)
132 if ('html' === $fhirElementName) {
133 return $jsonEntry;
136 if (false !== strpos($fhirElementName, '-primitive') || false !== strpos($fhirElementName, '-list')) {
137 return $jsonEntry;
140 $map = $this->_tryGetMapEntry($fhirElementName);
142 $fullClassName = $map['fullClassName'];
143 $properties = $map['properties'];
145 $object = new $fullClassName();
147 // This indicates we are at a primitive value...
148 if (is_scalar($jsonEntry)) {
149 if (isset($properties['value'])) {
150 $propertyMap = $properties['value'];
151 $setter = $propertyMap['setter'];
152 $element = $propertyMap['element'];
154 if (sprintf('%s-primitive', $fhirElementName) === $element || sprintf('%s-list', $fhirElementName) === $element) {
155 $object->$setter($jsonEntry);
156 } else {
157 $this->_triggerPropertyNotFoundError($fhirElementName, 'value');
159 } else {
160 $this->_triggerPropertyNotFoundError($fhirElementName, 'value');
162 } elseif (isset($jsonEntry['resourceType']) && $jsonEntry['resourceType'] !== $fhirElementName) { // TODO:
163 // This is probably very not ok...
164 $propertyMap = $properties[$jsonEntry['resourceType']];
165 $setter = $propertyMap['setter'];
166 $element = $propertyMap['element'];
167 $object->$setter($this->_parseJsonObject($jsonEntry, $element));
168 } else {
169 foreach ($jsonEntry as $k => $v) {
170 switch ($k) {
171 case 'resourceType':
172 case 'fhir_comments':
173 continue 2;
176 if (!isset($properties[$k])) {
177 $this->_triggerPropertyNotFoundError($fhirElementName, $k);
178 continue;
181 $propertyMap = $properties[$k];
182 $setter = $propertyMap['setter'];
183 $element = $propertyMap['element'];
185 if (is_array($v)) {
186 $firstKey = key($v);
188 if (is_string($firstKey)) {
189 $object->$setter($this->_parseJsonObject($v, $element));
190 } else {
191 foreach ($v as $child) {
192 $object->$setter($this->_parseJsonObject($child, $element));
195 } else {
196 $object->$setter($this->_parseJsonObject($v, $element));
201 return $object;
205 * @param \SimpleXMLElement $element
206 * @param string $fhirElementName
207 * @return mixed
209 private function _parseXMLNode(\SimpleXMLElement $element, $fhirElementName)
211 if ('html' === $fhirElementName) {
212 return $element->saveXML();
215 if (false !== strpos($fhirElementName, '-primitive') || false !== strpos($fhirElementName, '-list')) {
216 return (string)$element;
219 $map = $this->_tryGetMapEntry($fhirElementName);
221 $fullClassName = $map['fullClassName'];
222 $properties = $map['properties'];
224 $object = new $fullClassName();
226 /** @var \SimpleXMLElement $attribute */
227 foreach ($element->attributes() as $attribute) {
228 $childName = $attribute->getName();
229 if (!isset($properties[$childName])) {
230 $this->_triggerPropertyNotFoundError($fhirElementName, $childName);
231 continue;
234 $propertyMap = $properties[$childName];
235 $setter = $propertyMap['setter'];
237 $object->$setter((string)$attribute);
240 /** @var \SimpleXMLElement $childElement */
241 foreach ($element->children() as $childElement) {
242 $childName = $childElement->getName();
243 if (!isset($properties[$childName])) {
244 $this->_triggerPropertyNotFoundError($fhirElementName, $childName);
245 continue;
248 $propertyMap = $properties[$childName];
249 $setter = $propertyMap['setter'];
250 $element = $propertyMap['element'];
252 $object->$setter($this->_parseXMLNode($childElement, $element));
255 return $object;
259 * @param string $fhirElementName
260 * @return array
262 private function _tryGetMapEntry($fhirElementName)
264 if (!isset($this->_parserMap[$fhirElementName])) {
265 throw new \RuntimeException(sprintf(
266 'Element map does not contain entry for "%s". This indicates either malformed response or bug in class generation.',
267 $fhirElementName
271 return $this->_parserMap[$fhirElementName];
275 * @param string $fhirElementName
276 * @param string $propertyName
277 * @return bool
279 private function _triggerPropertyNotFoundError($fhirElementName, $propertyName)
281 return trigger_error(sprintf(
282 'Could not find mapped property called "%s" on object "%s". This could indicate malformed response or bug in class generator.',
283 $propertyName,
284 $fhirElementName
289 * @param mixed $input
290 * @return \InvalidArgumentException
292 private function _createNonStringArgumentException($input)
294 return new \InvalidArgumentException(sprintf(
295 '%s::parse - Argument 1 expected to be string, %s seen.',
296 get_called_class(),
297 gettype($input)
301 private static function _registerAutoloader()
303 $autoloaderClass = __NAMESPACE__ . '\PHPFHIRAutoloader';
304 $autoloaderClassFile = __DIR__ . '/PHPFHIRAutoloader.php';
306 if (!class_exists($autoloaderClass, false)) {
307 if (!file_exists($autoloaderClassFile)) {
308 throw new \RuntimeException(sprintf(
309 'PHPFHIRAutoloader class is not defined and was not found at expected location "%s".',
310 $autoloaderClassFile
314 require $autoloaderClassFile;
317 $autoloaderClass::register();