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