mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2025-01-21 21:01:15 +01:00
Add XML serialization and unserialization support
The unserializiation implementation currently is very hacky => needs some refactoring.
This commit is contained in:
parent
4e656fc58d
commit
b84553e011
@ -8,7 +8,7 @@ class PHPParser_Autoloader
|
||||
static public function register()
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array(new self, 'autoload'));
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -16,10 +16,24 @@ interface PHPParser_Node
|
||||
*/
|
||||
public function getLine();
|
||||
|
||||
/**
|
||||
* Sets line the node started in.
|
||||
*
|
||||
* @param int $line Line
|
||||
*/
|
||||
public function setLine($line);
|
||||
|
||||
/**
|
||||
* Gets the nearest doc comment.
|
||||
*
|
||||
* @return null|string Nearest doc comment or null
|
||||
*/
|
||||
public function getDocComment();
|
||||
|
||||
/**
|
||||
* Sets the nearest doc comment.
|
||||
*
|
||||
* @param null|string $docComment Nearest doc comment or null
|
||||
*/
|
||||
public function setDocComment($docComment);
|
||||
}
|
@ -37,6 +37,15 @@ abstract class PHPParser_NodeAbstract implements PHPParser_Node, IteratorAggrega
|
||||
return $this->line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets line the node started in.
|
||||
*
|
||||
* @param int $line Line
|
||||
*/
|
||||
public function setLine($line) {
|
||||
$this->line = (int) $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nearest doc comment.
|
||||
*
|
||||
@ -46,6 +55,15 @@ abstract class PHPParser_NodeAbstract implements PHPParser_Node, IteratorAggrega
|
||||
return $this->docComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nearest doc comment.
|
||||
*
|
||||
* @param null|string $docComment Nearest doc comment or null
|
||||
*/
|
||||
public function setDocComment($docComment) {
|
||||
$this->docComment = $docComment;
|
||||
}
|
||||
|
||||
/* Magic interfaces */
|
||||
|
||||
public function &__get($name) {
|
||||
|
13
lib/PHPParser/Serializer.php
Normal file
13
lib/PHPParser/Serializer.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
interface PHPParser_Serializer
|
||||
{
|
||||
/**
|
||||
* Serializes statements into some string format.
|
||||
*
|
||||
* @param array $nodes Statements
|
||||
*
|
||||
* @return string Serialized string
|
||||
*/
|
||||
public function serialize(array $nodes);
|
||||
}
|
74
lib/PHPParser/Serializer/XML.php
Normal file
74
lib/PHPParser/Serializer/XML.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
class PHPParser_Serializer_XML implements PHPParser_Serializer
|
||||
{
|
||||
protected $writer;
|
||||
|
||||
/**
|
||||
* Constructs a XML serializer.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->writer = new XMLWriter;
|
||||
$this->writer->openMemory();
|
||||
$this->writer->setIndent(true);
|
||||
}
|
||||
|
||||
public function serialize(array $nodes) {
|
||||
$this->writer->flush();
|
||||
$this->writer->startDocument('1.0', 'UTF-8');
|
||||
|
||||
$this->writer->startElement('AST');
|
||||
$this->writer->writeAttribute('xmlns:node', 'PHPParser/node');
|
||||
$this->writer->writeAttribute('xmlns:subNode', 'PHPParser/subNode');
|
||||
$this->writer->writeAttribute('xmlns:scalar', 'PHPParser/scalar');
|
||||
|
||||
$this->_serialize($nodes);
|
||||
|
||||
$this->writer->endElement();
|
||||
|
||||
return $this->writer->outputMemory();
|
||||
}
|
||||
|
||||
public function _serialize($node) {
|
||||
if ($node instanceof PHPParser_Node) {
|
||||
$this->writer->startElement('node:' . $node->getType());
|
||||
|
||||
if (-1 !== $line = $node->getLine()) {
|
||||
$this->writer->writeAttribute('line', $line);
|
||||
}
|
||||
|
||||
if (null !== $docComment = $node->getDocComment()) {
|
||||
$this->writer->writeAttribute('docComment', $docComment);
|
||||
}
|
||||
|
||||
foreach ($node as $name => $subNode) {
|
||||
$this->writer->startElement('subNode:' . $name);
|
||||
$this->_serialize($subNode);
|
||||
|
||||
$this->writer->endElement();
|
||||
}
|
||||
|
||||
$this->writer->endElement();
|
||||
} elseif (is_array($node)) {
|
||||
$this->writer->startElement('scalar:array');
|
||||
foreach ($node as $subNode) {
|
||||
$this->_serialize($subNode);
|
||||
}
|
||||
$this->writer->endElement();
|
||||
} elseif (is_string($node)) {
|
||||
$this->writer->writeElement('scalar:string', $node);
|
||||
} elseif (is_int($node)) {
|
||||
$this->writer->writeElement('scalar:int', $node);
|
||||
} elseif (is_float($node)) {
|
||||
$this->writer->writeElement('scalar:float', $node);
|
||||
} elseif (true === $node) {
|
||||
$this->writer->writeElement('scalar:true');
|
||||
} elseif (false === $node) {
|
||||
$this->writer->writeElement('scalar:false');
|
||||
} elseif (null === $node) {
|
||||
$this->writer->writeElement('scalar:null');
|
||||
} else {
|
||||
throw new Exception('Unexpected node type');
|
||||
}
|
||||
}
|
||||
}
|
13
lib/PHPParser/Unserializer.php
Normal file
13
lib/PHPParser/Unserializer.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
interface PHPParser_Unserializer
|
||||
{
|
||||
/**
|
||||
* Unserializes a string in some format into a node tree.
|
||||
*
|
||||
* @param string $string Serialized string
|
||||
*
|
||||
* @return array Statements
|
||||
*/
|
||||
public function unserialize($string);
|
||||
}
|
98
lib/PHPParser/Unserializer/XML.php
Normal file
98
lib/PHPParser/Unserializer/XML.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
class PHPParser_Unserializer_XML implements PHPParser_Unserializer
|
||||
{
|
||||
protected $reader;
|
||||
|
||||
public function __construct() {
|
||||
$this->reader = new XMLReader;
|
||||
}
|
||||
|
||||
public function unserialize($string) {
|
||||
$this->reader->XML($string);
|
||||
|
||||
$this->reader->read();
|
||||
if ('AST' !== $this->reader->name) {
|
||||
throw new Exception('AST root element not found');
|
||||
}
|
||||
|
||||
return $this->read();
|
||||
}
|
||||
|
||||
protected function read() {
|
||||
$depth = $this->reader->depth;
|
||||
while ($this->reader->read() && $depth <= $this->reader->depth) {
|
||||
if (XMLReader::ELEMENT !== $this->reader->nodeType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('node' === $this->reader->prefix) {
|
||||
$className = 'PHPParser_Node_' . $this->reader->localName;
|
||||
|
||||
// create the node without calling it's constructor
|
||||
$node = unserialize(
|
||||
sprintf('O:%d:"%s":0:{}', strlen($className), $className)
|
||||
);
|
||||
|
||||
$line = $this->reader->getAttribute('line');
|
||||
$node->setLine(null !== $line ? $line : -1);
|
||||
|
||||
$docComment = $this->reader->getAttribute('docComment');
|
||||
$node->setDocComment($docComment);
|
||||
|
||||
$depth2 = $this->reader->depth;
|
||||
while ($this->reader->read() && $depth2 < $this->reader->depth) {
|
||||
if (XMLReader::ELEMENT !== $this->reader->nodeType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('subNode' !== $this->reader->prefix) {
|
||||
throw new Exception('Expected sub node');
|
||||
}
|
||||
|
||||
$subNodeName = $this->reader->localName;
|
||||
$subNodeContent = $this->read();
|
||||
|
||||
$node->$subNodeName = $subNodeContent;
|
||||
}
|
||||
|
||||
return $node;
|
||||
} elseif ('scalar' === $this->reader->prefix) {
|
||||
if ('array' === $this->reader->localName) {
|
||||
$array = array();
|
||||
while ($node = $this->read()) {
|
||||
$array[] = $node;
|
||||
}
|
||||
return $array;
|
||||
} elseif ('string' === $this->reader->localName) {
|
||||
return $this->readText();
|
||||
} elseif ('int' === $this->reader->localName) {
|
||||
return (int) $this->readText();
|
||||
} elseif ('float' === $this->reader->localName) {
|
||||
return (float) $this->readText();
|
||||
} elseif ('false' === $this->reader->localName
|
||||
|| 'true' === $this->reader->localName
|
||||
|| 'null' === $this->reader->localName
|
||||
) {
|
||||
if ($this->reader->hasValue) {
|
||||
throw new Exception('false, true and null nodes cannot have a value');
|
||||
}
|
||||
|
||||
return constant($this->reader->localName);
|
||||
} else {
|
||||
throw new Exception('Unexpected scalar type');
|
||||
}
|
||||
} else {
|
||||
throw new Exception('Unexpected node type');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function readText() {
|
||||
if (!$this->reader->read() || XMLReader::TEXT !== $this->reader->nodeType) {
|
||||
throw new Exception('Expected text node');
|
||||
}
|
||||
|
||||
return $this->reader->value;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user