add simplexml_import_dom

This is needed for Symphony.

I copied the zend implementation and then cargocult programmed the rest from the other 2 functions in the file.

Closes #789
Esse commit está contido em:
Paul Tarjan
2013-05-20 00:11:56 -07:00
commit de Sara Golemon
commit d8d1e7f840
12 arquivos alterados com 295 adições e 16 exclusões
+161 -11
Ver Arquivo
@@ -3311,6 +3311,161 @@ class DirectoryIterator extends SplFileInfo implements Traversable,
}
// This doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/class.filesystemiterator.php )
*
* The Filesystem iterator
*
*/
class FilesystemIterator extends DirectoryIterator
implements SeekableIterator, Traversable, Iterator {
const CURRENT_AS_PATHNAME = 32;
const CURRENT_AS_FILEINFO = 0;
const CURRENT_AS_SELF = 16;
const CURRENT_MODE_MASK = 240;
const KEY_AS_PATHNAME = 0;
const KEY_AS_FILENAME = 256;
const FOLLOW_SYMLINKS = 512;
const KEY_MODE_MASK = 3840;
const NEW_CURRENT_AND_KEY = 256;
const SKIP_DOTS = 4096;
const UNIX_PATHS = 8192;
private $flags;
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.construct.php
* )
*
* Constructs a new filesystem iterator from the path.
*
* @path mixed The path of the filesystem item to be iterated over.
* @flags mixed Flags may be provided which will affect the behavior
* of some methods. A list of the flags can found under
* FilesystemIterator predefined constants. They can
* also be set later with
* FilesystemIterator::setFlags()
*
* @return mixed No value is returned.
*/
public function __construct(string $path, int $flags = null) {
parent::__construct($path);
if ($flags === null) {
$flags = FilesystemIterator::KEY_AS_PATHNAME |
FilesystemIterator::CURRENT_AS_FILEINFO |
FilesystemIterator::SKIP_DOTS;
}
$this->flags = $flags;
$this->goPastDotsIfNeeded();
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.current.php )
*
* Get file information of the current element.
*
* @return mixed The filename, file information, or $this depending
* on the set flags. See the FilesystemIterator
* constants.
*/
public function current() {
$f = parent::current();
if ($this->flags & FilesystemIterator::CURRENT_AS_PATHNAME) {
return $f->getPathname();
} else if ($this->flags & FilesystemIterator::CURRENT_AS_SELF) {
return $this;
}
// FilesystemIterator::CURRENT_AS_FILEINFO == 0
return $f;
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.getflags.php
* )
*
* Gets the handling flags, as set in FilesystemIterator::__construct() or
* FilesystemIterator::setFlags().
*
* @return mixed The integer value of the set flags.
*/
public function getFlags() {
return $this->flags;
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.key.php )
*
*
* @return mixed Returns the pathname or filename depending on the
* set flags. See the FilesystemIterator constants.
*/
public function key() {
if ($this->flags & FilesystemIterator::KEY_AS_FILENAME) {
return parent::current()->getFileName();
}
// FilesystemIterator::KEY_AS_PATHNAME == 0
return parent::current()->getPathName();
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.next.php )
*
* Move to the next file.
*
* @return mixed No value is returned.
*/
public function next() {
parent::next();
$this->goPastDotsIfNeeded();
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.rewind.php )
*
* Rewinds the directory back to the start.
*
* @return mixed No value is returned.
*/
public function rewind() {
parent::rewind();
$this->goPastDotsIfNeeded();
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from http://php.net/manual/en/filesystemiterator.setflags.php
* )
*
* Sets handling flags.
*
* @flags mixed The handling flags to set. See the
* FilesystemIterator constants.
*
* @return mixed No value is returned.
*/
public function setFlags(int $flags) {
$this->flags = $flags;
}
private function goPastDotsIfNeeded() {
if ($this->flags & FilesystemIterator::SKIP_DOTS) {
$f = parent::current();
while ($f && $f->isDot()) {
parent::next();
$f = parent::current();
}
}
}
}
// Do NOT modifiy this doc comment block generated by idl/sysdoc.php
/**
* ( excerpt from
* http://php.net/manual/en/class.recursivedirectoryiterator.php )
@@ -3319,15 +3474,8 @@ class DirectoryIterator extends SplFileInfo implements Traversable,
* recursively over filesystem directories.
*
*/
class RecursiveDirectoryIterator extends DirectoryIterator
class RecursiveDirectoryIterator extends FilesystemIterator
implements RecursiveIterator {
const CURRENT_AS_SELF = 0x0;
const CURRENT_AS_FILEINFO = 0x00000010;
const CURRENT_AS_PATHNAME = 0x00000020;
const KEY_AS_PATHNAME = 0x0;
const KEY_AS_FILENAME = 0x00000100;
const NEW_CURRENT_AND_KEY = 0x00000110;
// This doc comment block generated by idl/sysdoc.php
/**
@@ -3346,8 +3494,11 @@ class RecursiveDirectoryIterator extends DirectoryIterator
* @return mixed Returns the newly created
* RecursiveDirectoryIterator.
*/
function __construct($path,
$flags = RecursiveDirectoryIterator::CURRENT_AS_FILEINFO) {
function __construct($path, $flags = null) {
if ($flags === null) {
$flags = FilesystemIterator::KEY_AS_PATHNAME |
FilesystemIterator::CURRENT_AS_FILEINFO;
}
if (!hphp_recursivedirectoryiterator___construct($this, $path, $flags)) {
throw new UnexpectedValueException(
"RecursiveDirectoryIterator::__construct($path): failed to open dir");
@@ -3462,7 +3613,6 @@ class RecursiveDirectoryIterator extends DirectoryIterator
}
}
///////////////////////////////////////////////////////////////////////////////
// helpers
+25 -1
Ver Arquivo
@@ -83,6 +83,30 @@
}
]
},
{
"name": "simplexml_import_dom",
"desc": "This function takes a node of a DOM document and makes it into a SimpleXML node. This new object can then be used as a native SimpleXML element.",
"flags": [
"HasDocComment"
],
"return": {
"type": "Variant",
"desc": "Returns a SimpleXMLElement or FALSE on failure."
},
"args": [
{
"name": "node",
"type": "Variant",
"desc": "A DOM Element node"
},
{
"name": "class_name",
"type": "Variant",
"value": "\"SimpleXMLElement\"",
"desc": "You may use this optional parameter so that simplexml_load_file() will return an object of the specified class. That class should extend the SimpleXMLElement class."
}
]
},
{
"name": "libxml_get_errors",
"desc": "Retrieve array of errors.",
@@ -699,4 +723,4 @@
]
}
]
}
}
+51 -4
Ver Arquivo
@@ -18,9 +18,9 @@
#include "hphp/runtime/ext/ext_simplexml.h"
#include "hphp/runtime/ext/ext_file.h"
#include "hphp/runtime/ext/ext_class.h"
#include "hphp/runtime/ext/ext_domdocument.h"
#include "hphp/runtime/base/class_info.h"
#include "hphp/runtime/base/util/request_local.h"
#include "hphp/system/lib/systemlib.h"
#ifndef LIBXML2_NEW_BUFFER
@@ -42,13 +42,19 @@ public:
// overriding ResourceData
virtual CStrRef o_getClassNameHook() const { return s_class_name; }
XmlDocWrapper(xmlDocPtr doc, CStrRef cls)
: m_doc(doc), m_cls(cls) { }
XmlDocWrapper(xmlDocPtr doc, CStrRef cls, Object domNode = nullptr)
: m_doc(doc), m_cls(cls), m_domNode(domNode) {
if (!domNode.isNull()) {
DEBUG_ONLY c_DOMNode *domnode = domNode.getTyped<c_DOMNode>();
assert(!domnode || domnode->m_node == (xmlNodePtr) doc);
}
}
CStrRef getClass() { return m_cls; }
void sweep() {
if (m_doc) {
// if m_domNode isn't null, then he owns the m_doc. Otherwise, I own it
if (m_doc && m_domNode.isNull()) {
xmlFreeDoc(m_doc);
}
}
@@ -56,6 +62,8 @@ public:
private:
xmlDocPtr m_doc;
String m_cls;
// Hold onto the original owner of the doc so it doesn't get free()d.
Object m_domNode;
};
IMPLEMENT_OBJECT_ALLOCATION_NO_DEFAULT_SWEEP(XmlDocWrapper)
@@ -236,6 +244,45 @@ static void add_registered_namespaces(Array &out, xmlNodePtr node,
static StaticString s_SimpleXMLElement("SimpleXMLElement");
Variant f_simplexml_import_dom(CVarRef node,
CVarRef class_name /* = "SimpleXMLElement" */) {
if (!node.isObject()) {
raise_warning(
"simplexml_import_dom() expects parameter 1 to be object"
);
return uninit_null();
}
if (!class_name.isString()) {
raise_warning(
"simplexml_import_dom() expects parameter 2 to be string"
);
return uninit_null();
}
c_DOMNode *domnode = node.asCObjRef().getTyped<c_DOMNode>();
xmlNodePtr nodep = domnode->m_node;
if (nodep) {
if (nodep->doc == nullptr) {
raise_warning("Imported Node must have associated Document");
return uninit_null();
}
if (nodep->type == XML_DOCUMENT_NODE ||
nodep->type == XML_HTML_DOCUMENT_NODE) {
nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
}
}
if (nodep && nodep->type == XML_ELEMENT_NODE) {
Object obj = Object(NEWOBJ(XmlDocWrapper)(nodep->doc, class_name, node));
return create_element(obj, nodep, String(), false);
} else {
raise_warning("Invalid Nodetype to import");
return uninit_null();
}
}
Variant f_simplexml_load_string(CStrRef data,
CStrRef class_name /* = "SimpleXMLElement" */,
int64_t options /* = 0 */,
+2
Ver Arquivo
@@ -25,6 +25,8 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
Variant f_simplexml_import_dom(CVarRef node,
CVarRef class_name = "SimpleXMLElement");
Variant f_simplexml_load_string(CStrRef data, CStrRef class_name = "SimpleXMLElement", int64_t options = 0, CStrRef ns = "", bool is_prefix = false);
Variant f_simplexml_load_file(CStrRef filename, CStrRef class_name = "SimpleXMLElement", int64_t options = 0, CStrRef ns = "", bool is_prefix = false);
Variant f_libxml_get_errors();
+7
Ver Arquivo
@@ -5901,6 +5901,13 @@ const char *g_class_map[] = {
NULL,
NULL,
NULL,
(const char *)0x10006040, "simplexml_import_dom", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from\n * http://php.net/manual/en/function.simplexml-import-dom.php )\n *\n * This function takes a node of a DOM document and makes it into a\n * SimpleXML node. This new object can then be used as a native SimpleXML\n * element.\n *\n * @node mixed A DOM Element node\n * @class_name mixed You may use this optional parameter so that\n * simplexml_load_file() will return an object of the\n * specified class. That class should extend the\n * SimpleXMLElement class.\n *\n * @return mixed Returns a SimpleXMLElement or FALSE on failure.\n */",
(const char *)0xffffffff /* KindOfUnknown: $t: Variant */, (const char *)0x2000, "node", "", (const char *)0xffffffff /* KindOfUnknown: $t: Variant */, "", (const char *)0, "", (const char *)0, NULL,
(const char *)0x2000, "class_name", "", (const char *)0xffffffff /* KindOfUnknown: $t: Variant */, "s:16:\"SimpleXMLElement\";", (const char *)24, "\"SimpleXMLElement\"", (const char *)18, NULL,
NULL,
NULL,
NULL,
(const char *)0x10006040, "libxml_get_errors", "", (const char*)0, (const char*)0,
"/**\n * ( excerpt from http://php.net/manual/en/function.libxml-get-errors.php )\n *\n * Retrieve array of errors.\n *\n * @return mixed Returns an array with LibXMLError objects if there\n * are any errors in the buffer, or an empty array\n * otherwise.\n */",
(const char *)0xffffffff /* KindOfUnknown: $t: Variant */, NULL,
@@ -0,0 +1,20 @@
<?php
$string = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:other="http://other.w3.org/other" >
<id>uYG7-sPwjFg</id>
<published>2009-05-17T18:29:31.000Z</published>
</entry>
EOT;
$doc = new DOMDocument;
$doc->loadXML($string);
$xml = simplexml_import_dom($doc);
$xml->registerXPathNamespace('atom', "http://www.w3.org/2005/Atom");
$nodes = $xml->xpath('//atom:entry/atom:published/text()');
foreach ($nodes as $node) {
print $node;
}
@@ -0,0 +1 @@
2009-05-17T18:29:31.000Z
@@ -0,0 +1,17 @@
<?php
function main() {
$dom = new domDocument;
$string = <<<END
<a>
<b>c</b>
</a>
END;
$dom->loadXML($string);
$s = simplexml_import_dom($dom);
$dom = null;
var_dump((string) $s->b);
}
main();
@@ -0,0 +1 @@
string(1) "c"
+10
Ver Arquivo
@@ -0,0 +1,10 @@
<books>
<book>
<title>The Grapes of Wrath</title>
<author>John Steinbeck</author>
</book>
<book>
<title>The Pearl</title>
<author>John Steinbeck</author>
</book>
</books>