1 | <?php |
||||||
2 | |||||||
3 | namespace Xml\Impl\Instance; |
||||||
4 | |||||||
5 | use Xml\Impl\ModelInstanceImpl; |
||||||
6 | use Xml\Instance\{ |
||||||
7 | DomDocumentInterface, |
||||||
8 | DomElementInterface, |
||||||
9 | ModelElementInstanceInterface |
||||||
10 | }; |
||||||
11 | use Xml\Impl\Util\XmlQName; |
||||||
12 | use Xml\Impl\Util\DomUtil; |
||||||
13 | |||||||
14 | class DomElementImpl implements DomElementInterface |
||||||
15 | { |
||||||
16 | private const MODEL_ELEMENT_KEY = "example.modelElementRef"; |
||||||
17 | private const XMLNS_ATTRIBUTE_NS_URI = "http://www.w3.org/2000/xmlns/"; |
||||||
18 | private const XMLNS_ATTRIBUTE = "xmlns"; |
||||||
19 | |||||||
20 | private $element; |
||||||
21 | |||||||
22 | private $document; |
||||||
23 | |||||||
24 | private $modelElementInstance; |
||||||
0 ignored issues
–
show
introduced
by
![]() |
|||||||
25 | |||||||
26 | public function __construct(DomElementExt $element) |
||||||
27 | { |
||||||
28 | $this->element = $element; |
||||||
29 | $this->document = $element->ownerDocument; |
||||||
30 | } |
||||||
31 | |||||||
32 | public function getElement(): ?DomElementExt |
||||||
33 | { |
||||||
34 | return $this->element; |
||||||
35 | } |
||||||
36 | |||||||
37 | public function getNamespaceURI(): string |
||||||
38 | { |
||||||
39 | return $this->element->namespaceURI; |
||||||
0 ignored issues
–
show
|
|||||||
40 | } |
||||||
41 | |||||||
42 | public function getLocalName(): string |
||||||
43 | { |
||||||
44 | return $this->element->localName; |
||||||
45 | } |
||||||
46 | |||||||
47 | public function getPrefix(): string |
||||||
48 | { |
||||||
49 | return $this->element->prefix; |
||||||
0 ignored issues
–
show
|
|||||||
50 | } |
||||||
51 | |||||||
52 | public function getDocument(): ?DomDocumentInterface |
||||||
53 | { |
||||||
54 | $ownerDocument = $this->element->ownerDocument; |
||||||
55 | if ($ownerDocument !== null) { |
||||||
56 | return new DomDocumentImpl($ownerDocument); |
||||||
57 | } else { |
||||||
58 | return null; |
||||||
59 | } |
||||||
60 | } |
||||||
61 | |||||||
62 | public function getRootElement(): ?DomElementInterface |
||||||
63 | { |
||||||
64 | $document = $this->getDocument(); |
||||||
65 | if ($document !== null) { |
||||||
66 | return $document->getRootElement(); |
||||||
67 | } else { |
||||||
68 | return null; |
||||||
69 | } |
||||||
70 | } |
||||||
71 | |||||||
72 | public function getParentElement(): ?DomElementInterface |
||||||
73 | { |
||||||
74 | $parentNode = $this->element->parentNode; |
||||||
75 | if ($parentNode !== null && $parentNode instanceof DomElementExt) { |
||||||
76 | return new DomElementImpl($parentNode); |
||||||
77 | } else { |
||||||
78 | return null; |
||||||
79 | } |
||||||
80 | } |
||||||
81 | |||||||
82 | public function getChildElements(): array |
||||||
83 | { |
||||||
84 | $childNodes = $this->element->childNodes; |
||||||
85 | return DomUtil::filterNodeListForElements($childNodes); |
||||||
86 | } |
||||||
87 | |||||||
88 | /** |
||||||
89 | * @param mixed $uris |
||||||
90 | * @param string $elementName |
||||||
91 | */ |
||||||
92 | public function getChildElementsByNameNs($uris, string $elementName): array |
||||||
93 | { |
||||||
94 | $childNodes = $this->element->childNodes; |
||||||
95 | $result = []; |
||||||
96 | if (is_string($uris)) { |
||||||
97 | $result = DomUtil::filterNodeListByName($childNodes, $uris, $elementName); |
||||||
98 | } elseif (is_array($uris)) { |
||||||
99 | foreach ($uris as $uri) { |
||||||
100 | $result = array_merge($result, DomUtil::filterNodeListByName($childNodes, $uri, $elementName)); |
||||||
101 | } |
||||||
102 | } |
||||||
103 | return $result; |
||||||
104 | } |
||||||
105 | |||||||
106 | |||||||
107 | public function getChildElementsByType( |
||||||
108 | ModelInstanceImpl $modelInstance, |
||||||
109 | string $elementType |
||||||
110 | ): array { |
||||||
111 | $childNodes = $this->element->childNodes; |
||||||
112 | return DomUtil::filterNodeListByType($childNodes, $modelInstance, $elementType); |
||||||
113 | } |
||||||
114 | |||||||
115 | public function replaceChild( |
||||||
116 | DomElementInterface $newChildDomElement, |
||||||
117 | DomElementInterface $existingChildDomElement |
||||||
118 | ): void { |
||||||
119 | $newElement = $newChildDomElement->getElement(); |
||||||
120 | $existingElement = $existingChildDomElement->getElement(); |
||||||
121 | if ($this->element->replaceChild($newElement, $existingElement) === false) { |
||||||
0 ignored issues
–
show
It seems like
$existingElement can also be of type null ; however, parameter $child of DOMNode::replaceChild() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() It seems like
$newElement can also be of type null ; however, parameter $node of DOMNode::replaceChild() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
122 | throw new \DOMException("Unable to replace child element with new element"); |
||||||
123 | } |
||||||
124 | } |
||||||
125 | |||||||
126 | public function removeChild(DomElementInterface $childDomElement): bool |
||||||
127 | { |
||||||
128 | $childElement = $childDomElement->getElement(); |
||||||
129 | try { |
||||||
130 | $this->element->removeChild($childElement); |
||||||
0 ignored issues
–
show
It seems like
$childElement can also be of type null ; however, parameter $child of DOMNode::removeChild() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
131 | return true; |
||||||
132 | } catch (\Exception $e) { |
||||||
133 | return false; |
||||||
134 | } |
||||||
135 | } |
||||||
136 | |||||||
137 | public function appendChild(DomElementInterface $childDomElement): void |
||||||
138 | { |
||||||
139 | $childElement = $childDomElement->getElement(); |
||||||
140 | $this->element->appendChild($childElement); |
||||||
0 ignored issues
–
show
It seems like
$childElement can also be of type null ; however, parameter $node of DOMNode::appendChild() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
141 | } |
||||||
142 | |||||||
143 | public function insertChildElementAfter( |
||||||
144 | DomElementInterface $elementToInsert, |
||||||
145 | ?DomElementInterface $insertAfter |
||||||
146 | ): void { |
||||||
147 | $newElement = $elementToInsert->getElement(); |
||||||
148 | if ($insertAfter === null) { |
||||||
149 | $insertBeforeNode = $this->element->firstChild; |
||||||
150 | } else { |
||||||
151 | $insertBeforeNode = $insertAfter->getElement()->nextSibling; |
||||||
152 | } |
||||||
153 | |||||||
154 | if ($insertBeforeNode !== null) { |
||||||
155 | $this->element->insertBefore($newElement, $insertBeforeNode); |
||||||
0 ignored issues
–
show
It seems like
$newElement can also be of type null ; however, parameter $node of DOMNode::insertBefore() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
156 | } else { |
||||||
157 | $this->element->appendChild($newElement); |
||||||
0 ignored issues
–
show
It seems like
$newElement can also be of type null ; however, parameter $node of DOMNode::appendChild() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
158 | } |
||||||
159 | } |
||||||
160 | |||||||
161 | public function hasAttribute(?string $namespaceUri, string $localName): bool |
||||||
162 | { |
||||||
163 | if ($namespaceUri === null) { |
||||||
164 | return $this->element->hasAttribute($localName); |
||||||
165 | } else { |
||||||
166 | return $this->element->hasAttributeNS($namespaceUri, $localName); |
||||||
167 | } |
||||||
168 | } |
||||||
169 | |||||||
170 | public function getAttribute(?string $namespaceUri, string $localName): ?string |
||||||
171 | { |
||||||
172 | $xmlQName = new XmlQName($this->getDocument(), $this, $namespaceUri, $localName); |
||||||
173 | if ($xmlQName->hasLocalNamespace()) { |
||||||
174 | $value = $this->element->getAttribute($xmlQName->getLocalName()); |
||||||
175 | } else { |
||||||
176 | $value = $this->element->getAttributeNS($xmlQName->getNamespaceUri(), $xmlQName->getLocalName()); |
||||||
177 | } |
||||||
178 | |||||||
179 | if (empty($value)) { |
||||||
180 | return null; |
||||||
181 | } else { |
||||||
182 | return $value; |
||||||
183 | } |
||||||
184 | } |
||||||
185 | |||||||
186 | public function setAttribute(?string $namespaceUri, string $localName, string $value, ?bool $isIdAttribute = false): void |
||||||
187 | { |
||||||
188 | $isIdAttribute = $isIdAttribute ?? false; |
||||||
189 | $xmlQName = new XmlQName($this->getDocument(), $this, $namespaceUri, $localName); |
||||||
190 | if ($xmlQName->hasLocalNamespace()) { |
||||||
191 | $this->element->setAttribute($xmlQName->getLocalName(), $value); |
||||||
192 | if ($isIdAttribute && !$this->element->getAttributeNode($localName)->isId()) { |
||||||
193 | $this->element->setIdAttribute($xmlQName->getLocalName(), true); |
||||||
194 | } |
||||||
195 | } else { |
||||||
196 | //PHP does not create prefix automatically, like Java |
||||||
197 | $prefixedName = $xmlQName->getPrefixedName(); |
||||||
198 | if (strpos($prefixedName, ":") === false) { |
||||||
199 | $prefix = $this->getDocument()->getUnusedGenericNsPrefix(); |
||||||
200 | $prefixedName = $prefix . ":" . $localName; |
||||||
201 | } |
||||||
202 | $this->element->setAttributeNS($xmlQName->getNamespaceUri(), $prefixedName, $value); |
||||||
203 | if ($isIdAttribute && !$this->element->getAttributeNodeNS($xmlQName->getNamespaceUri(), $localName)->isId()) { |
||||||
204 | $this->element->setIdAttributeNS($xmlQName->getNamespaceUri(), $xmlQName->getLocalName(), true); |
||||||
205 | } |
||||||
206 | } |
||||||
207 | } |
||||||
208 | |||||||
209 | public function setIdAttribute(?string $namespaceUri, string $localName, string $value): void |
||||||
210 | { |
||||||
211 | $namespaceUri = $namespaceUri ?? $this->getNamespaceURI(); |
||||||
212 | $this->setAttribute($namespaceUri, $localName, $value, true); |
||||||
213 | } |
||||||
214 | |||||||
215 | public function removeAttribute(?string $namespaceUri, string $localName): void |
||||||
216 | { |
||||||
217 | $namespaceUri = $namespaceUri ?? $this->getNamespaceURI(); |
||||||
218 | $xmlQName = new XmlQName($this->getDocument(), $this, $namespaceUri, $localName); |
||||||
219 | if ($xmlQName->hasLocalNamespace()) { |
||||||
220 | $this->element->removeAttribute($xmlQName->getLocalName()); |
||||||
221 | } else { |
||||||
222 | $this->element->removeAttributeNS($xmlQName->getNamespaceUri(), $xmlQName->getLocalName()); |
||||||
223 | } |
||||||
224 | } |
||||||
225 | |||||||
226 | public function getTextContent(): string |
||||||
227 | { |
||||||
228 | return $this->element->textContent; |
||||||
229 | } |
||||||
230 | |||||||
231 | public function setTextContent(string $textContent): void |
||||||
232 | { |
||||||
233 | $this->element->nodeValue = $textContent; |
||||||
234 | } |
||||||
235 | |||||||
236 | public function addCDataSection(string $data): void |
||||||
237 | { |
||||||
238 | $document = $this->getDocument(); |
||||||
239 | $cdataSection = $document->createCDATASection($data); |
||||||
0 ignored issues
–
show
The method
createCDATASection() does not exist on Xml\Impl\Instance\DomDocumentImpl .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||||
240 | $this->element->appendChild($cdataSection); |
||||||
241 | } |
||||||
242 | |||||||
243 | public function getModelElementInstance(): ?ModelElementInstanceInterface |
||||||
244 | { |
||||||
245 | //return $this->modelElementInstance; |
||||||
246 | return $this->element->getUserData(self::MODEL_ELEMENT_KEY); |
||||||
247 | } |
||||||
248 | |||||||
249 | public function setModelElementInstance(ModelElementInstanceInterface $modelElementInstance): void |
||||||
250 | { |
||||||
251 | //$this->modelElementInstance = $modelElementInstance; |
||||||
252 | $this->element->setUserData(self::MODEL_ELEMENT_KEY, $modelElementInstance, null); |
||||||
253 | } |
||||||
254 | |||||||
255 | /** |
||||||
256 | * @return mixed |
||||||
257 | */ |
||||||
258 | public function registerNamespace(?string $prefix, string $namespaceUri) |
||||||
259 | { |
||||||
260 | if ($prefix !== null) { |
||||||
261 | $this->element->setAttributeNS( |
||||||
262 | self::XMLNS_ATTRIBUTE_NS_URI, |
||||||
263 | self::XMLNS_ATTRIBUTE . ":" . $prefix, |
||||||
264 | $namespaceUri |
||||||
265 | ); |
||||||
266 | } else { |
||||||
267 | $lookupPrefix = $this->lookupPrefix($namespaceUri); |
||||||
268 | if ($lookupPrefix === null) { |
||||||
269 | if (array_key_exists($namespaceUri, XmlQName::KNOWN_PREFIXES)) { |
||||||
270 | $prefix = XmlQName::KNOWN_PREFIXES[$namespaceUri]; |
||||||
271 | } |
||||||
272 | if ( |
||||||
273 | $prefix !== null && |
||||||
274 | $this->getRootElement() !== null && |
||||||
275 | $this->getRootElement()->element->hasAttributeNS(self::XMLNS_ATTRIBUTE_NS_URI, $prefix) |
||||||
276 | ) { |
||||||
277 | $prefix = null; |
||||||
278 | } |
||||||
279 | if ($prefix === null) { |
||||||
280 | $prefix = $this->getDocument()->getUnusedGenericNsPrefix(); |
||||||
281 | } |
||||||
282 | $this->registerNamespace($prefix, $namespaceUri); |
||||||
283 | return $prefix; |
||||||
284 | } else { |
||||||
285 | return $lookupPrefix; |
||||||
286 | } |
||||||
287 | } |
||||||
288 | } |
||||||
289 | |||||||
290 | public function lookupPrefix(string $namespaceUri): ?string |
||||||
291 | { |
||||||
292 | return $this->element->lookupPrefix($namespaceUri); |
||||||
293 | } |
||||||
294 | |||||||
295 | public function equals(?DomElementInterface $obj): bool |
||||||
296 | { |
||||||
297 | if ($obj === null) { |
||||||
298 | return false; |
||||||
299 | } |
||||||
300 | |||||||
301 | return $this->element->isSameNode($obj->getElement()); |
||||||
0 ignored issues
–
show
It seems like
$obj->getElement() can also be of type null ; however, parameter $otherNode of DOMNode::isSameNode() does only seem to accept DOMNode , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
302 | } |
||||||
303 | } |
||||||
304 |