Skip to content

Commit bee65c0

Browse files
committed
Se refactoriza XmlDocument para usar composición en vez de herencia con DOMDocument.
1 parent d8f8c70 commit bee65c0

9 files changed

Lines changed: 200 additions & 142 deletions

File tree

src/Contract/DOMDocumentInterface.php

Lines changed: 19 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,31 @@
1212

1313
namespace Derafu\Xml\Contract;
1414

15+
use DOMDocument;
1516
use DOMElement;
16-
use DOMNodeList;
17-
use DOMParentNode;
1817

1918
/**
20-
* Interface for the class that represents an XML document.
19+
* Interface for the underlying DOM document access.
2120
*
22-
* This interface exists so that other interfaces that extend DOMDocument, such
23-
* as XmlDocument, can resolve the methods that use the official PHP
24-
* DOMDocument. These methods should not be implemented if you extend
25-
* DOMDocument. It is only for the IDE and syntactic analyzers to not generate
26-
* warnings in the interface.
27-
*
28-
* @see DOMDocument
21+
* Exposes the minimal DOM surface needed by XmlDocumentInterface: access to
22+
* the raw DOMDocument, the document element, and canonicalization. All other
23+
* DOM operations (mutation, validation) are handled by the services that need
24+
* them via getDomDocument().
2925
*/
30-
interface DOMDocumentInterface extends DOMParentNode
26+
interface DOMDocumentInterface
3127
{
3228
/**
33-
* Returns the root element instance of the document.
29+
* Returns the underlying DOMDocument instance.
3430
*
35-
* This is a safe way to access $documentElement when using this interface
36-
* as a variable type.
31+
* Provides an escape hatch for services (encoder, validator) that need
32+
* direct DOM access without polluting the XmlDocument public API.
3733
*
38-
* If you do not use this, tools like phpstan will complain.
34+
* @return DOMDocument
35+
*/
36+
public function getDomDocument(): DOMDocument;
37+
38+
/**
39+
* Returns the root element instance of the document.
3940
*
4041
* @return DOMElement|null
4142
*/
@@ -44,86 +45,16 @@ public function getDocumentElement(): ?DOMElement;
4445
/**
4546
* Canonicalizes the XML according to the C14N specification.
4647
*
47-
* The official implementation of this interface inherits from DOMDocument
48-
* so this method is available. However, it is defined in the interface so
49-
* that tools like phpstan do not complain when using this interface as a
50-
* variable type.
51-
*
5248
* @param bool $exclusive Indicates if exclusive canonicalization is used.
5349
* @param bool $withComments Includes comments in the output if `true`.
54-
* @param array|null $xpath Optional list of nodes to include in the
55-
* canonicalization.
56-
* @param array|null $nsPrefixes Prefixes of namespaces to consider in the
57-
* canonicalization.
58-
* @return string|false A string with the canonicalized XML or `false` in
59-
* case of error.
50+
* @param array|null $xpath Optional list of nodes to include.
51+
* @param array|null $nsPrefixes Namespace prefixes to consider.
52+
* @return string|false Canonicalized XML or `false` on error.
6053
*/
6154
public function C14N(
6255
bool $exclusive = false,
6356
bool $withComments = false,
6457
?array $xpath = null,
6558
?array $nsPrefixes = null
6659
): string|false;
67-
68-
/**
69-
* Creates a new element in the XML document.
70-
*
71-
* The official implementation of this interface inherits from DOMDocument
72-
* so this method is available. However, it is defined in the interface so
73-
* that tools like phpstan do not complain when using this interface as a
74-
* variable type.
75-
*
76-
* @param string $localName The local name of the element.
77-
* @param string $value The optional value of the element.
78-
* @return DOMElement|false The created element or `false` in case of error.
79-
*/
80-
public function createElement(
81-
string $localName,
82-
string $value = ''
83-
); // Adding a return type is incompatible with the official DOMDocument of PHP.
84-
85-
/**
86-
* Creates a new element in a specific namespace.
87-
*
88-
* The official implementation of this interface inherits from DOMDocument
89-
* so this method is available. However, it is defined in the interface so
90-
* that tools like phpstan do not complain when using this interface as a
91-
* variable type.
92-
*
93-
* @param string|null $namespace The URI of the namespace (can be `null` for
94-
* none).
95-
* @param string $qualifiedName The qualified name of the element.
96-
* @param string $value The optional value of the element.
97-
* @return DOMElement|false The created element or `false` in case of error.
98-
*/
99-
public function createElementNS(
100-
?string $namespace,
101-
string $qualifiedName,
102-
string $value = ''
103-
); // Adding a return type is incompatible with the official DOMDocument of PHP.
104-
105-
/**
106-
* Validates the current XML document against an XML schema.
107-
*
108-
* The official implementation of this interface inherits from DOMDocument
109-
* so this method is available. However, it is defined in the interface so
110-
* that tools like phpstan do not complain when using this interface as a
111-
* variable type.
112-
*
113-
* @param string $filename The path to the schema file (.xsd).
114-
* @param int $flags Validation options (default `0`).
115-
* @return bool `true` if validation is successful, `false` in case of error.
116-
*/
117-
public function schemaValidate(string $filename, int $flags = 0): bool;
118-
119-
/**
120-
* Gets a list of nodes (DOMNodeList) using a tag name.
121-
*
122-
* Searches for all elements of the current document that match the
123-
* provided tag name (regardless of which part of the tree they are in).
124-
*
125-
* @param string $qualifiedName The qualified name of the tag to search for.
126-
* @return DOMNodeList A list of nodes that match the tag.
127-
*/
128-
public function getElementsByTagName(string $qualifiedName): DOMNodeList;
12960
}

src/Service/XmlEncoder.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function encode(array $data): XmlDocumentInterface
4747
{
4848
$doc = new XmlDocument();
4949

50-
$this->encodeNode($data, $doc, $doc);
50+
$this->encodeNode($data, $doc, $doc->getDomDocument());
5151

5252
return $doc;
5353
}
@@ -181,15 +181,15 @@ private function nodeAddChilds(
181181
));
182182
}
183183

184-
$Node = $doc->createElement($tagName);
184+
$Node = $doc->getDomDocument()->createElement($tagName);
185185
$parent->appendChild($Node);
186186
$this->encodeNode($child, $doc, $Node);
187187
}
188188
// If the child is not an array, it is simply a duplicate node that
189189
// must be added at the same level as the parent node.
190190
else {
191191
$value = XmlHelper::sanitize((string) $child);
192-
$Node = $doc->createElement($tagName, $value);
192+
$Node = $doc->getDomDocument()->createElement($tagName, $value);
193193
$parent->appendChild($Node);
194194
}
195195
}
@@ -211,7 +211,7 @@ private function nodeAddValue(
211211
string $value,
212212
): void {
213213
$value = XmlHelper::sanitize($value);
214-
$Node = $doc->createElement($tagName, $value);
214+
$Node = $doc->getDomDocument()->createElement($tagName, $value);
215215
$parent->appendChild($Node);
216216
}
217217

src/Service/XmlValidator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function validate(
9090
$useInternalErrors = libxml_use_internal_errors(true);
9191

9292
// Validate the XML document.
93-
$isValid = $xml->schemaValidate($schemaPath);
93+
$isValid = $xml->getDomDocument()->schemaValidate($schemaPath);
9494

9595
// Get errors, clear them and restore the state of errors of libxml.
9696
$errors = libxml_get_errors();

src/XPathQuery.php

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
namespace Derafu\Xml;
1414

1515
use Derafu\Xml\Contract\XmlDocumentInterface;
16-
use Derafu\Xml\Exception\XmlParseException;
1716
use Derafu\Xml\Exception\XmlQueryException;
1817
use DOMDocument;
1918
use DOMNode;
@@ -57,11 +56,14 @@ public function __construct(
5756
array $namespaces = []
5857
) {
5958
// Assign the DOM document instance.
60-
if ($xml instanceof XmlDocumentInterface || $xml instanceof DOMDocument) {
59+
if ($xml instanceof XmlDocumentInterface) {
60+
$this->dom = $xml->getDomDocument();
61+
} elseif ($xml instanceof DOMDocument) {
6162
$this->dom = $xml;
6263
} else {
63-
$this->dom = new XmlDocument();
64-
$this->loadXml($xml);
64+
$xmlDoc = new XmlDocument();
65+
$xmlDoc->loadXml($xml);
66+
$this->dom = $xmlDoc->getDomDocument();
6567
}
6668

6769
// Create the XPath instance over the DOM document.
@@ -206,21 +208,6 @@ public function getNodes(
206208
return $nodes;
207209
}
208210

209-
/**
210-
* Loads an XML string into the $dom attribute.
211-
*
212-
* @param string $xml
213-
* @return static
214-
*/
215-
private function loadXml(string $xml): static
216-
{
217-
// XmlDocument::loadXml() throws XmlParseException if the XML is
218-
// empty or malformed, propagating it directly to the caller.
219-
$this->dom->loadXml($xml);
220-
221-
return $this;
222-
}
223-
224211
/**
225212
* Processes a DOM node and its children recursively.
226213
*

0 commit comments

Comments
 (0)