XML.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <?php
  2. namespace PhpParser\Unserializer;
  3. use DomainException;
  4. use PhpParser\Unserializer;
  5. use XMLReader;
  6. /**
  7. * @deprecated
  8. */
  9. class XML implements Unserializer
  10. {
  11. protected $reader;
  12. public function __construct() {
  13. $this->reader = new XMLReader;
  14. }
  15. public function unserialize($string) {
  16. $this->reader->XML($string);
  17. $this->reader->read();
  18. if ('AST' !== $this->reader->name) {
  19. throw new DomainException('AST root element not found');
  20. }
  21. return $this->read($this->reader->depth);
  22. }
  23. protected function read($depthLimit, $throw = true, &$nodeFound = null) {
  24. $nodeFound = true;
  25. while ($this->reader->read() && $depthLimit < $this->reader->depth) {
  26. if (XMLReader::ELEMENT !== $this->reader->nodeType) {
  27. continue;
  28. }
  29. if ('node' === $this->reader->prefix) {
  30. return $this->readNode();
  31. } elseif ('scalar' === $this->reader->prefix) {
  32. return $this->readScalar();
  33. } elseif ('comment' === $this->reader->name) {
  34. return $this->readComment();
  35. } else {
  36. throw new DomainException(sprintf('Unexpected node of type "%s"', $this->reader->name));
  37. }
  38. }
  39. $nodeFound = false;
  40. if ($throw) {
  41. throw new DomainException('Expected node or scalar');
  42. }
  43. }
  44. protected function readNode() {
  45. $className = $this->getClassNameFromType($this->reader->localName);
  46. // create the node without calling it's constructor
  47. $node = unserialize(
  48. sprintf(
  49. "O:%d:\"%s\":1:{s:13:\"\0*\0attributes\";a:0:{}}",
  50. strlen($className), $className
  51. )
  52. );
  53. $depthLimit = $this->reader->depth;
  54. while ($this->reader->read() && $depthLimit < $this->reader->depth) {
  55. if (XMLReader::ELEMENT !== $this->reader->nodeType) {
  56. continue;
  57. }
  58. $type = $this->reader->prefix;
  59. if ('subNode' !== $type && 'attribute' !== $type) {
  60. throw new DomainException(
  61. sprintf('Expected sub node or attribute, got node of type "%s"', $this->reader->name)
  62. );
  63. }
  64. $name = $this->reader->localName;
  65. $value = $this->read($this->reader->depth);
  66. if ('subNode' === $type) {
  67. $node->$name = $value;
  68. } else {
  69. $node->setAttribute($name, $value);
  70. }
  71. }
  72. return $node;
  73. }
  74. protected function readScalar() {
  75. switch ($name = $this->reader->localName) {
  76. case 'array':
  77. $depth = $this->reader->depth;
  78. $array = array();
  79. while (true) {
  80. $node = $this->read($depth, false, $nodeFound);
  81. if (!$nodeFound) {
  82. break;
  83. }
  84. $array[] = $node;
  85. }
  86. return $array;
  87. case 'string':
  88. return $this->reader->readString();
  89. case 'int':
  90. return $this->parseInt($this->reader->readString());
  91. case 'float':
  92. $text = $this->reader->readString();
  93. if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) {
  94. throw new DomainException(sprintf('"%s" is not a valid float', $text));
  95. }
  96. return $float;
  97. case 'true':
  98. case 'false':
  99. case 'null':
  100. if (!$this->reader->isEmptyElement) {
  101. throw new DomainException(sprintf('"%s" scalar must be empty', $name));
  102. }
  103. return constant($name);
  104. default:
  105. throw new DomainException(sprintf('Unknown scalar type "%s"', $name));
  106. }
  107. }
  108. private function parseInt($text) {
  109. if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) {
  110. throw new DomainException(sprintf('"%s" is not a valid integer', $text));
  111. }
  112. return $int;
  113. }
  114. protected function readComment() {
  115. $className = $this->reader->getAttribute('isDocComment') === 'true'
  116. ? 'PhpParser\Comment\Doc'
  117. : 'PhpParser\Comment'
  118. ;
  119. return new $className(
  120. $this->reader->readString(),
  121. $this->parseInt($this->reader->getAttribute('line'))
  122. );
  123. }
  124. protected function getClassNameFromType($type) {
  125. $className = 'PhpParser\\Node\\' . strtr($type, '_', '\\');
  126. if (!class_exists($className)) {
  127. $className .= '_';
  128. }
  129. if (!class_exists($className)) {
  130. throw new DomainException(sprintf('Unknown node type "%s"', $type));
  131. }
  132. return $className;
  133. }
  134. }