diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md
index f7021f59a4598..6a63e88d78534 100644
--- a/src/Symfony/Component/VarDumper/CHANGELOG.md
+++ b/src/Symfony/Component/VarDumper/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+7.1
+---
+
+ * Add support for new DOM extension classes in `DOMCaster`
+
7.0
---
diff --git a/src/Symfony/Component/VarDumper/Caster/DOMCaster.php b/src/Symfony/Component/VarDumper/Caster/DOMCaster.php
index ca1ffcea6ad59..52bd31c4489c6 100644
--- a/src/Symfony/Component/VarDumper/Caster/DOMCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/DOMCaster.php
@@ -63,7 +63,7 @@ class DOMCaster
\XML_NAMESPACE_DECL_NODE => 'XML_NAMESPACE_DECL_NODE',
];
- public static function castException(\DOMException $e, array $a, Stub $stub, bool $isNested): array
+ public static function castException(\DOMException|\DOM\Exception $e, array $a, Stub $stub, bool $isNested): array
{
$k = Caster::PREFIX_PROTECTED.'code';
if (isset($a[$k], self::ERROR_CODES[$a[$k]])) {
@@ -82,7 +82,7 @@ public static function castLength($dom, array $a, Stub $stub, bool $isNested): a
return $a;
}
- public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castImplementation(\DOMImplementation|\DOM\Implementation $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
Caster::PREFIX_VIRTUAL.'Core' => '1.0',
@@ -92,7 +92,7 @@ public static function castImplementation(\DOMImplementation $dom, array $a, Stu
return $a;
}
- public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castNode(\DOMNode|\DOM\Node $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'nodeName' => $dom->nodeName,
@@ -104,15 +104,20 @@ public static function castNode(\DOMNode $dom, array $a, Stub $stub, bool $isNes
'lastChild' => new CutStub($dom->lastChild),
'previousSibling' => new CutStub($dom->previousSibling),
'nextSibling' => new CutStub($dom->nextSibling),
- 'attributes' => $dom->attributes,
'ownerDocument' => new CutStub($dom->ownerDocument),
- 'namespaceURI' => $dom->namespaceURI,
- 'prefix' => $dom->prefix,
- 'localName' => $dom->localName,
'baseURI' => $dom->baseURI ? new LinkStub($dom->baseURI) : $dom->baseURI,
'textContent' => new CutStub($dom->textContent),
];
+ if ($dom instanceof \DOMNode || $dom instanceof \DOM\Element) {
+ $a += [
+ 'attributes' => $dom->attributes,
+ 'namespaceURI' => $dom->namespaceURI,
+ 'prefix' => $dom->prefix,
+ 'localName' => $dom->localName,
+ ];
+ }
+
return $a;
}
@@ -166,7 +171,48 @@ public static function castDocument(\DOMDocument $dom, array $a, Stub $stub, boo
return $a;
}
- public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castXMLDocument(\DOM\XMLDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array
+ {
+ $a += [
+ 'doctype' => $dom->doctype,
+ 'implementation' => $dom->implementation,
+ 'documentElement' => new CutStub($dom->documentElement),
+ 'inputEncoding' => $dom->inputEncoding,
+ 'xmlEncoding' => $dom->xmlEncoding,
+ 'xmlStandalone' => $dom->xmlStandalone,
+ 'xmlVersion' => $dom->xmlVersion,
+ 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,
+ 'formatOutput' => $dom->formatOutput,
+ ];
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE)) {
+ $formatOutput = $dom->formatOutput;
+ $dom->formatOutput = true;
+ $a += [Caster::PREFIX_VIRTUAL.'xml' => $dom->saveXML()];
+ $dom->formatOutput = $formatOutput;
+ }
+
+ return $a;
+ }
+
+ public static function castHTMLDocument(\DOM\HTMLDocument $dom, array $a, Stub $stub, bool $isNested, int $filter = 0): array
+ {
+ $a += [
+ 'doctype' => $dom->doctype,
+ 'implementation' => $dom->implementation,
+ 'documentElement' => new CutStub($dom->documentElement),
+ 'inputEncoding' => $dom->inputEncoding,
+ 'documentURI' => $dom->documentURI ? new LinkStub($dom->documentURI) : $dom->documentURI,
+ ];
+
+ if (!($filter & Caster::EXCLUDE_VERBOSE)) {
+ $a += [Caster::PREFIX_VIRTUAL.'html' => $dom->saveHTML()];
+ }
+
+ return $a;
+ }
+
+ public static function castCharacterData(\DOMCharacterData|\DOM\CharacterData $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'data' => $dom->data,
@@ -176,30 +222,40 @@ public static function castCharacterData(\DOMCharacterData $dom, array $a, Stub
return $a;
}
- public static function castAttr(\DOMAttr $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castAttr(\DOMAttr|\DOM\Attr $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'name' => $dom->name,
'specified' => $dom->specified,
'value' => $dom->value,
'ownerElement' => $dom->ownerElement,
- 'schemaTypeInfo' => $dom->schemaTypeInfo,
];
+ if ($dom instanceof \DOMAttr) {
+ $a += [
+ 'schemaTypeInfo' => $dom->schemaTypeInfo,
+ ];
+ }
+
return $a;
}
- public static function castElement(\DOMElement $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castElement(\DOMElement|\DOM\Element $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'tagName' => $dom->tagName,
- 'schemaTypeInfo' => $dom->schemaTypeInfo,
];
+ if ($dom instanceof \DOMElement) {
+ $a += [
+ 'schemaTypeInfo' => $dom->schemaTypeInfo,
+ ];
+ }
+
return $a;
}
- public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castText(\DOMText|\DOM\Text $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'wholeText' => $dom->wholeText,
@@ -208,7 +264,7 @@ public static function castText(\DOMText $dom, array $a, Stub $stub, bool $isNes
return $a;
}
- public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castDocumentType(\DOMDocumentType|\DOM\DocumentType $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'name' => $dom->name,
@@ -222,7 +278,7 @@ public static function castDocumentType(\DOMDocumentType $dom, array $a, Stub $s
return $a;
}
- public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castNotation(\DOMNotation|\DOM\Notation $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'publicId' => $dom->publicId,
@@ -232,7 +288,7 @@ public static function castNotation(\DOMNotation $dom, array $a, Stub $stub, boo
return $a;
}
- public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castEntity(\DOMEntity|\DOM\Entity $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'publicId' => $dom->publicId,
@@ -246,7 +302,7 @@ public static function castEntity(\DOMEntity $dom, array $a, Stub $stub, bool $i
return $a;
}
- public static function castProcessingInstruction(\DOMProcessingInstruction $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castProcessingInstruction(\DOMProcessingInstruction|\DOM\ProcessingInstruction $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'target' => $dom->target,
@@ -256,7 +312,7 @@ public static function castProcessingInstruction(\DOMProcessingInstruction $dom,
return $a;
}
- public static function castXPath(\DOMXPath $dom, array $a, Stub $stub, bool $isNested): array
+ public static function castXPath(\DOMXPath|\DOM\XPath $dom, array $a, Stub $stub, bool $isNested): array
{
$a += [
'document' => $dom->document,
diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
index e7cb39469a58f..addab129747a6 100644
--- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
+++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
@@ -54,23 +54,38 @@ abstract class AbstractCloner implements ClonerInterface
'Doctrine\Persistence\ObjectManager' => ['Symfony\Component\VarDumper\Caster\StubCaster', 'cutInternals'],
'DOMException' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'],
+ 'DOM\Exception' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castException'],
'DOMStringList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
'DOMNameList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
'DOMImplementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'],
+ 'DOM\Implementation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castImplementation'],
'DOMImplementationList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
'DOMNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'],
+ 'DOM\Node' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNode'],
'DOMNameSpaceNode' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNameSpaceNode'],
'DOMDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocument'],
+ 'DOM\XMLDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXMLDocument'],
+ 'DOM\HTMLDocument' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castHTMLDocument'],
'DOMNodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOM\NodeList' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
'DOMNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
+ 'DOM\DTDNamedNodeMap' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castLength'],
'DOMCharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'],
+ 'DOM\CharacterData' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castCharacterData'],
'DOMAttr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'],
+ 'DOM\Attr' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castAttr'],
'DOMElement' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'],
+ 'DOM\Element' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castElement'],
'DOMText' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'],
+ 'DOM\Text' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castText'],
'DOMDocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'],
+ 'DOM\DocumentType' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castDocumentType'],
'DOMNotation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'],
+ 'DOM\Notation' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castNotation'],
'DOMEntity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'],
+ 'DOM\Entity' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castEntity'],
'DOMProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'],
+ 'DOM\ProcessingInstruction' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castProcessingInstruction'],
'DOMXPath' => ['Symfony\Component\VarDumper\Caster\DOMCaster', 'castXPath'],
'XMLReader' => ['Symfony\Component\VarDumper\Caster\XmlReaderCaster', 'castXmlReader'],
diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DOMCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DOMCasterTest.php
new file mode 100644
index 0000000000000..81cdc120ccd34
--- /dev/null
+++ b/src/Symfony/Component/VarDumper/Tests/Caster/DOMCasterTest.php
@@ -0,0 +1,303 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\VarDumper\Tests\Caster;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
+
+class DOMCasterTest extends TestCase
+{
+ use VarDumperTestTrait;
+
+ public function testCastImplementation()
+ {
+ $implementation = new \DOMImplementation();
+
+ $this->assertDumpEquals(<<<'EODUMP'
+ DOMImplementation {
+ Core: "1.0"
+ XML: "2.0"
+ }
+ EODUMP, $implementation);
+ }
+
+ /**
+ * @requires PHP 8.4
+ */
+ public function testCastModernImplementation()
+ {
+ $implementation = new \DOM\Implementation();
+
+ $this->assertDumpEquals(<<<'EODUMP'
+ DOM\Implementation {
+ Core: "1.0"
+ XML: "2.0"
+ }
+ EODUMP, $implementation);
+ }
+
+ public function testCastNode()
+ {
+ $doc = new \DOMDocument();
+ $doc->loadXML('
foo
'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\HTMLDocument {%A + html: "foo
" + } + EODUMP, $doc); + } + + public function testCastText() + { + $doc = new \DOMText('foo'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOMText {%A + +wholeText: ? string + } + EODUMP, $doc); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernText() + { + $text = \DOM\HTMLDocument::createEmpty()->createTextNode('foo'); + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\Text {%A + +wholeText: ? string + } + EODUMP, $text); + } + + public function testCastAttr() + { + $attr = new \DOMAttr('attr', 'value'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOMAttr {%A + +name: ? string + +specified: true + +value: ? string + +ownerElement: ? ?DOMElement + +schemaTypeInfo: null + } + EODUMP, $attr); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernAttr() + { + $attr = \DOM\HTMLDocument::createEmpty()->createAttribute('attr'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\Attr {%A + +name: ? string + +value: ? string + +ownerElement: ? ?DOM\Element + +specified: true + } + EODUMP, $attr); + } + + public function testCastElement() + { + $attr = new \DOMElement('foo'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOMElement {%A + +tagName: ? string + %A} + EODUMP, $attr); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernElement() + { + $attr = \DOM\HTMLDocument::createEmpty()->createElement('foo'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\Element {%A + +tagName: ? string + %A} + EODUMP, $attr); + } + + public function testCastDocumentType() + { + $implementation = new \DOMImplementation(); + $type = $implementation->createDocumentType('html', 'publicId', 'systemId'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOMDocumentType {%A + +name: ? string + +entities: ? DOMNamedNodeMap + +notations: ? DOMNamedNodeMap + +publicId: ? string + +systemId: ? string + +internalSubset: ? ?string + } + EODUMP, $type); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernDocumentType() + { + $implementation = new \DOM\Implementation(); + $type = $implementation->createDocumentType('html', 'publicId', 'systemId'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\DocumentType {%A + +name: ? string + +entities: ? DOM\DTDNamedNodeMap + +notations: ? DOM\DTDNamedNodeMap + +publicId: ? string + +systemId: ? string + +internalSubset: ? ?string + } + EODUMP, $type); + } + + public function testCastProcessingInstruction() + { + $entity = new \DOMProcessingInstruction('target', 'data'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOMProcessingInstruction {%A + +target: ? string + +data: ? string + } + EODUMP, $entity); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernProcessingInstruction() + { + $entity = \DOM\HTMLDocument::createEmpty()->createProcessingInstruction('target', 'data'); + + $this->assertDumpMatchesFormat(<<<'EODUMP' + DOM\ProcessingInstruction {%A + +data: ? string + +length: ? int + +target: ? string + } + EODUMP, $entity); + } + + public function testCastXPath() + { + $xpath = new \DOMXPath(new \DOMDocument()); + + $this->assertDumpEquals(<<<'EODUMP' + DOMXPath { + +document: ? DOMDocument + +registerNodeNamespaces: ? bool + } + EODUMP, $xpath); + } + + /** + * @requires PHP 8.4 + */ + public function testCastModernXPath() + { + $entity = new \DOM\XPath(\DOM\HTMLDocument::createEmpty()); + + $this->assertDumpEquals(<<<'EODUMP' + DOM\XPath { + +document: ? DOM\Document + +registerNodeNamespaces: ? bool + } + EODUMP, $entity); + } +}