PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.4
Booking for Appointments and Events Calendar – Amelia v2.4.4
2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / vendor / apimatic / core / src / Utils / XmlDeserializer.php
ameliabooking / vendor / apimatic / core / src / Utils Last commit date
CoreHelper.php 1 year ago DateHelper.php 1 year ago JsonHelper.php 1 year ago XmlDeserializer.php 1 year ago XmlSerializer.php 1 year ago
XmlDeserializer.php
223 lines
1 <?php
2
3 declare(strict_types=1);
4
5 namespace Core\Utils;
6
7 use DOMDocument;
8 use Exception;
9
10 class XmlDeserializer
11 {
12 /**
13 * @var DOMDocument
14 */
15 private $dom;
16
17 /**
18 * @int
19 */
20 private $loadOptions;
21
22 /**
23 * @param int|null $loadOptions A bit field of LIBXML_* constants
24 */
25 public function __construct(int $loadOptions = null)
26 {
27 $this->dom = new DOMDocument();
28 $this->loadOptions = $loadOptions ?? (LIBXML_NONET | LIBXML_NOBLANKS);
29 }
30
31 public function deserialize(string $xml, string $rootName, string $clazz)
32 {
33 $this->dom->loadXML($xml, $this->loadOptions);
34 return $this->fromElement($this->dom, $rootName, $clazz);
35 }
36
37 public function deserializeToArray(
38 string $xml,
39 string $rootName,
40 string $itemName,
41 string $clazz
42 ) {
43 $this->dom->loadXML($xml, $this->loadOptions);
44 return $this->fromElementToArray($this->dom, $itemName, $clazz, $rootName);
45 }
46
47 public function deserializeToMap(
48 string $xml,
49 string $rootName,
50 string $clazz
51 ) {
52 $this->dom->loadXML($xml, $this->loadOptions);
53 return $this->fromElementToMap($this->dom, $rootName, $clazz);
54 }
55
56 public function fromAttribute(\DOMElement $parent, string $name, string $clazz)
57 {
58 if (!$parent->hasAttribute($name)) {
59 static::assertNullable($parent, '@' . $name, $clazz);
60 return null;
61 }
62
63 $attributeValue = $parent->getAttribute($name);
64
65 return $this->convertSimple($parent->getAttributeNode($name), $attributeValue, $clazz);
66 }
67
68 public function fromElement(\DOMNode $parent, string $name, string $clazz)
69 {
70 $element = static::getChildNodeByTagName($parent, $name);
71
72 if ($element === null) {
73 static::assertNullable($parent, $name . '[1]', $clazz);
74 return null;
75 }
76
77 return $this->convert($element, $clazz);
78 }
79
80 public function fromElementToArray(
81 \DOMNode $parent,
82 string $itemName,
83 string $clazz,
84 string $wrappingElementName = null
85 ) {
86 if ($wrappingElementName === null) {
87 $elements = static::getChildNodesByTagName($parent, $itemName);
88 } else {
89 $wrappingElement = static::getChildNodeByTagName($parent, $wrappingElementName);
90
91 if ($wrappingElement === null) {
92 static::assertNullable($parent, $wrappingElementName . '[1]', $clazz);
93 return null;
94 }
95
96 $elements = static::getChildNodesByTagName($wrappingElement, $itemName);
97 }
98
99 return \array_map(
100 function ($element) use ($clazz) {
101 return $this->convert($element, $clazz);
102 },
103 $elements
104 );
105 }
106
107 public function fromElementToMap(
108 \DOMNode $parent,
109 string $name,
110 string $clazz
111 ) {
112 $wrapper = static::getChildNodeByTagName($parent, $name);
113
114 if ($wrapper === null) {
115 static::assertNullable($parent, $name . '[1]', $clazz);
116 return null;
117 }
118
119 $map = [];
120 foreach ($wrapper->childNodes as $element) {
121 if ($element->nodeType === XML_ELEMENT_NODE && $element->hasAttribute('key') === true) {
122 $map[$element->getAttribute('key')] = $this->convert($element, $clazz);
123 }
124 }
125
126 return $map;
127 }
128
129 private function convert(\DOMElement $node, string $clazz)
130 {
131 $type = static::withoutNullQualifier($clazz);
132
133 if (\class_exists($type) && \method_exists($type, 'fromXmlElement')) {
134 return \call_user_func([$type, 'fromXmlElement'], $this, $node);
135 }
136
137 return $this->convertSimple($node, $node->textContent, $clazz);
138 }
139
140 private function convertSimple(\DOMNode $node, string $value, string $clazz)
141 {
142 $type = static::withoutNullQualifier($clazz);
143
144 if ($type === 'float') {
145 return \is_numeric($value) ? \floatval($value) : static::throwTypeException($node, $value, $clazz);
146 } elseif ($type === 'int') {
147 return \is_numeric($value) ? \intval($value) : static::throwTypeException($node, $value, $clazz);
148 } elseif ($type === 'bool') {
149 return \strcasecmp($value, 'true') === 0 ?:
150 (\strcasecmp($value, 'false') === 0 ? false : static::throwTypeException($node, $value, $clazz));
151 }
152
153 return $value;
154 }
155
156 private static function assertNullable(\DOMNode $parentNode, string $nodeSubPath, string $clazz): void
157 {
158 if ($clazz[0] === '?') {
159 return;
160 }
161
162 $sourceNodePath = static::makeNodePath($parentNode, $nodeSubPath);
163
164 throw new Exception(
165 'Required value not found at XML path "' . $sourceNodePath . '" during deserialization.'
166 );
167 }
168
169 private static function throwTypeException(\DOMNode $sourceNode, $value, string $clazz): void
170 {
171 throw new Exception(
172 'Expected value of type "' . $clazz . '" but got value "' . $value . '" at XML path "' .
173 $sourceNode->getNodePath() . '" during deserialization.'
174 );
175 }
176
177 private static function withoutNullQualifier(string $type): string
178 {
179 if (\strlen($type) > 1 && $type[0] === '?') {
180 return \substr($type, 1);
181 }
182
183 return $type;
184 }
185
186 private static function makeNodePath(\DOMNode $node, $subpath)
187 {
188 $parentPath = $node->getNodePath();
189 if ($parentPath === '/') {
190 $parentPath = '';
191 }
192
193 return $parentPath . '/' . $subpath;
194 }
195
196 private static function getChildNodeByTagName(\DOMNode $node, string $name): ?\DOMElement
197 {
198 if ($node->hasChildNodes()) {
199 foreach ($node->childNodes as $childNode) {
200 if ($childNode->nodeType === XML_ELEMENT_NODE && $childNode->tagName === $name) {
201 return $childNode;
202 }
203 }
204 }
205
206 return null;
207 }
208
209 private static function getChildNodesByTagName(\DOMNode $node, string $name): array
210 {
211 $arr = [];
212 if ($node->hasChildNodes()) {
213 foreach ($node->childNodes as $childNode) {
214 if ($childNode->nodeType === XML_ELEMENT_NODE && $childNode->tagName === $name) {
215 $arr[] = $childNode;
216 }
217 }
218 }
219
220 return $arr;
221 }
222 }
223