Skip to content

[Dumper] Add support for XmlReader objets #18989

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
156 changes: 156 additions & 0 deletions src/Symfony/Component/VarDumper/Caster/XmlReaderCaster.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\VarDumper\Caster;

use Symfony\Component\VarDumper\Cloner\Stub;

/**
* Casts XmlReader class to array representation.
*
* @author Baptiste Clavié <clavie.b@gmail.com>
*/
class XmlReaderCaster
{
private static $nodeTypes = array(
\XmlReader::NONE => 'NONE',
\XmlReader::ELEMENT => 'ELEMENT',
\XmlReader::ATTRIBUTE => 'ATTRIBUTE',
\XmlReader::TEXT => 'TEXT',
\XmlReader::CDATA => 'CDATA',
\XmlReader::ENTITY_REF => 'ENTITY_REF',
\XmlReader::ENTITY => 'ENTITY',
\XmlReader::PI => 'PI',
\XmlReader::COMMENT => 'COMMENT',
\XmlReader::DOC => 'DOC',
\XmlReader::DOC_TYPE => 'DOC_TYPE',
\XmlReader::DOC_FRAGMENT => 'DOC_FRAGMENT',
\XmlReader::NOTATION => 'NOTATION',
\XmlReader::WHITESPACE => 'WHITESPACE',
\XmlReader::SIGNIFICANT_WHITESPACE => 'SIGNIFICANT_WHITESPACE',
\XmlReader::END_ELEMENT => 'END_ELEMENT',
\XmlReader::END_ENTITY => 'END_ENTITY',
\XmlReader::XML_DECLARATION => 'XML_DECLARATION',
);

private static $filteredTypes = array(
\XmlReader::ENTITY_REF => true,
\XmlReader::ENTITY => true,
\XmlReader::PI => true,
\XmlReader::DOC => true,
\XmlReader::DOC_TYPE => true,
\XmlReader::DOC_FRAGMENT => true,
\XmlReader::NOTATION => true,
\XmlReader::WHITESPACE => true,
\XmlReader::SIGNIFICANT_WHITESPACE => true,
\XmlReader::END_ELEMENT => true,
\XmlReader::END_ENTITY => true,
);

public static function castXmlReader(\XmlReader $reader, array $a, Stub $stub, $isNested)
Copy link
Member

@nicolas-grekas nicolas-grekas Jun 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would adopt a different code organization: let's start by building the full $infos array without any conditional statement, then filter based on the type. This should help reduce duplications, and ease counting cut value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't do that, as NONE elements triggers fatal errors when trying to access the name or other properties. I thought of making some "special" cases, such as NONE and ATTRIBUTES, but then I could treat the filter afterwards and make a difference in the number of elements, as was done before.

{
$nodeType = new ConstStub(self::$nodeTypes[$reader->nodeType], $reader->nodeType);
$parserProperties = new EnumStub(array(
'LOADDTD' => $reader->getParserProperty(\XmlReader::LOADDTD),
'DEFAULTATTRS' => $reader->getParserProperty(\XmlReader::DEFAULTATTRS),
'VALIDATE' => $reader->getParserProperty(\XmlReader::VALIDATE),
'SUBST_ENTITIES' => $reader->getParserProperty(\XmlReader::SUBST_ENTITIES),
));

if (\XmlReader::NONE === $reader->nodeType) {
return $a + self::castXmlNone($nodeType, $parserProperties);
}

if (\XmlReader::ATTRIBUTE === $reader->nodeType) {
return $a + self::castAttribute($reader, $nodeType, $parserProperties);
}

$infos = array(
'localName' => $reader->localName,
'nodeType' => $nodeType,
'depth' => $reader->depth,
'attributeCount' => $reader->attributeCount,
'hasAttributes' => $reader->hasAttributes,
'hasValue' => $reader->hasValue,
'isDefault' => $reader->isDefault,
'isEmptyElement' => $reader->isEmptyElement,
);

if ('' !== $reader->prefix) {
$infos['prefix'] = $reader->prefix;
$infos['namespaceURI'] = $reader->namespaceURI;
}

if ($reader->hasValue && \XmlReader::TEXT === $reader->nodeType) {
$infos['value'] = $reader->value;
}

if ($reader->hasAttributes) {
$infos[Caster::PREFIX_VIRTUAL.'attributes'] = array();

for ($i = 0; $i < $reader->attributeCount; ++$i) {
$infos[Caster::PREFIX_VIRTUAL.'attributes'][] = $reader->getAttributeNo($i);
}
}

if (isset(self::$filteredTypes[$reader->nodeType])) {
$infos = self::castFilteredElement($reader, $infos, $stub, $nodeType);
}

$infos[Caster::PREFIX_VIRTUAL.'parserProperties'] = $parserProperties;

return $a + $infos;
}

private static function castXmlNone(ConstStub $type, EnumStub $properties)
{
return array(
'nodeType' => $type,
Caster::PREFIX_VIRTUAL.'parserProperties' => $properties,
);
}

private static function castFilteredElement(\XmlReader $reader, array $infos, Stub $stub, ConstStub $type)
{
$cut = array(
'localName' => $reader->localName,
'nodeType' => $type,
'depth' => $reader->depth,
);

$stub->cut += count($infos) - count($cut);

return $cut;
}

private static function castAttribute(\XmlReader $reader, ConstStub $type, EnumStub $properties)
{
$infos = array(
'localName' => $reader->localName,
'nodeType' => $type,
'depth' => $reader->depth,
'isDefault' => $reader->isDefault,
'hasValue' => $reader->hasValue,
);

if ($reader->hasValue) {
$infos['value'] = $reader->value;
}

if ('' !== $reader->prefix) {
$infos['prefix'] = $reader->prefix;
$infos['namespaceURI'] = $reader->namespaceURI;
}

$infos[Caster::PREFIX_VIRTUAL.'parserProperties'] = $properties;

return $infos;
}
}
2 changes: 2 additions & 0 deletions src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ abstract class AbstractCloner implements ClonerInterface
'DOMProcessingInstruction' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castProcessingInstruction',
'DOMXPath' => 'Symfony\Component\VarDumper\Caster\DOMCaster::castXPath',

'XmlReader' => 'Symfony\Component\VarDumper\Caster\XmlReaderCaster::castXmlReader',

'ErrorException' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castErrorException',
'Exception' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castException',
'Error' => 'Symfony\Component\VarDumper\Caster\ExceptionCaster::castError',
Expand Down
Loading