Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php declare(strict_types=1);namespace PhpParser;class JsonDecoder{/** @var \ReflectionClass[] Node type to reflection class map */private $reflectionClassCache;public function decode(string $json) {$value = json_decode($json, true);if (json_last_error()) {throw new \RuntimeException('JSON decoding error: ' . json_last_error_msg());}return $this->decodeRecursive($value);}private function decodeRecursive($value) {if (\is_array($value)) {if (isset($value['nodeType'])) {if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {return $this->decodeComment($value);}return $this->decodeNode($value);}return $this->decodeArray($value);}return $value;}private function decodeArray(array $array) : array {$decodedArray = [];foreach ($array as $key => $value) {$decodedArray[$key] = $this->decodeRecursive($value);}return $decodedArray;}private function decodeNode(array $value) : Node {$nodeType = $value['nodeType'];if (!\is_string($nodeType)) {throw new \RuntimeException('Node type must be a string');}$reflectionClass = $this->reflectionClassFromNodeType($nodeType);/** @var Node $node */$node = $reflectionClass->newInstanceWithoutConstructor();if (isset($value['attributes'])) {if (!\is_array($value['attributes'])) {throw new \RuntimeException('Attributes must be an array');}$node->setAttributes($this->decodeArray($value['attributes']));}foreach ($value as $name => $subNode) {if ($name === 'nodeType' || $name === 'attributes') {continue;}$node->$name = $this->decodeRecursive($subNode);}return $node;}private function decodeComment(array $value) : Comment {$className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;if (!isset($value['text'])) {throw new \RuntimeException('Comment must have text');}return new $className($value['text'],$value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1,$value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1);}private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass {if (!isset($this->reflectionClassCache[$nodeType])) {$className = $this->classNameFromNodeType($nodeType);$this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);}return $this->reflectionClassCache[$nodeType];}private function classNameFromNodeType(string $nodeType) : string {$className = 'PhpParser\\Node\\' . strtr($nodeType, '_', '\\');if (class_exists($className)) {return $className;}$className .= '_';if (class_exists($className)) {return $className;}throw new \RuntimeException("Unknown node type \"$nodeType\"");}}