Implement Dom\HTMLElement class

This commit is contained in:
Niels Dossche 2024-04-27 21:23:29 +02:00
parent 78401ba867
commit 48c9f1e2c3
11 changed files with 58 additions and 20 deletions

View file

@ -44,6 +44,7 @@ extern PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_modern_attr_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_modern_element_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_html_element_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_modern_text_class_entry;
extern PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry;

View file

@ -1423,7 +1423,8 @@ zend_result dom_html_document_body_write(dom_object *obj, zval *newval)
dom_object *newval_intern = Z_DOMOBJ_P(newval);
if (newval_intern->ptr != NULL) {
xmlNodePtr newval_node = ((php_libxml_node_ptr *) newval_intern->ptr)->node;
if (php_dom_ns_is_fast(newval_node, php_dom_ns_is_html_magic_token) && dom_accept_body_name(newval_node->name)) {
/* Note: because this property has type HTMLElement, we know the namespace is correct. */
if (dom_accept_body_name(newval_node->name)) {
/* 2. If the new value is the same as the body element, return. */
const xmlNode *current_body_element = dom_html_document_element_read_raw(docp, dom_accept_body_name);
if (current_body_element == newval_node) {

View file

@ -47,7 +47,6 @@ static zend_always_inline zend_class_entry *dom_get_dtd_namednodemap_ce(bool mod
DOM_DEF_GET_CE_FUNC(node)
DOM_DEF_GET_CE_FUNC(documenttype)
DOM_DEF_GET_CE_FUNC(element)
DOM_DEF_GET_CE_FUNC(attr)
DOM_DEF_GET_CE_FUNC(entity)
DOM_DEF_GET_CE_FUNC(entityreference)

View file

@ -63,6 +63,7 @@ PHP_DOM_EXPORT zend_class_entry *dom_attr_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_modern_attr_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_element_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_modern_element_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_html_element_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_text_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_modern_text_class_entry;
PHP_DOM_EXPORT zend_class_entry *dom_comment_class_entry;
@ -1042,6 +1043,11 @@ PHP_MINIT_FUNCTION(dom)
DOM_OVERWRITE_PROP_HANDLER(&dom_modern_element_prop_handlers, "textContent", dom_node_text_content_read, dom_node_text_content_write);
zend_hash_add_new_ptr(&classes, dom_modern_element_class_entry->name, &dom_modern_element_prop_handlers);
dom_html_element_class_entry = register_class_Dom_HTMLElement(dom_modern_element_class_entry);
dom_html_element_class_entry->create_object = dom_objects_new;
dom_html_element_class_entry->default_object_handlers = &dom_object_handlers;
zend_hash_add_new_ptr(&classes, dom_html_element_class_entry->name, &dom_modern_element_prop_handlers);
dom_text_class_entry = register_class_DOMText(dom_characterdata_class_entry);
dom_text_class_entry->create_object = dom_objects_new;
dom_text_class_entry->default_object_handlers = &dom_object_handlers;
@ -1541,6 +1547,19 @@ void php_dom_create_iterator(zval *return_value, dom_iterator_type iterator_type
}
/* }}} */
static zend_always_inline zend_class_entry *dom_get_element_ce(const xmlNode *node, bool modern)
{
if (modern) {
if (php_dom_ns_is_fast(node, php_dom_ns_is_html_magic_token)) {
return dom_html_element_class_entry;
} else {
return dom_modern_element_class_entry;
}
} else {
return dom_element_class_entry;
}
}
/* {{{ php_dom_create_object */
PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, dom_object *domobj)
{
@ -1572,7 +1591,7 @@ PHP_DOM_EXPORT bool php_dom_create_object(xmlNodePtr obj, zval *return_value, do
}
case XML_ELEMENT_NODE:
{
ce = dom_get_element_ce(modern);
ce = dom_get_element_ce(obj, modern);
break;
}
case XML_ATTRIBUTE_NODE:

View file

@ -1374,6 +1374,10 @@ namespace Dom
public function replaceChildren(Node|string ...$nodes): void {}
}
class HTMLElement extends Element
{
}
class Attr extends Node
{
/** @readonly */
@ -1581,9 +1585,9 @@ namespace Dom
public function importLegacyNode(\DOMNode $node, bool $deep = false): Node {}
public ?Element $body;
public ?HTMLElement $body;
/** @readonly */
public ?Element $head;
public ?HTMLElement $head;
public string $title;
}

View file

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 7a2c28838f431eff28dea8cc5356dbcd38921592 */
* Stub hash: eda699f0d524fae5ae76a3a395438a16989c2af8 */
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 0)
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
@ -1674,6 +1674,10 @@ static const zend_function_entry class_Dom_Element_methods[] = {
ZEND_FE_END
};
static const zend_function_entry class_Dom_HTMLElement_methods[] = {
ZEND_FE_END
};
static const zend_function_entry class_Dom_Attr_methods[] = {
ZEND_RAW_FENTRY("isId", zim_DOMAttr_isId, arginfo_class_Dom_Attr_isId, ZEND_ACC_PUBLIC, NULL, NULL)
ZEND_FE_END
@ -3080,6 +3084,16 @@ static zend_class_entry *register_class_Dom_Element(zend_class_entry *class_entr
return class_entry;
}
static zend_class_entry *register_class_Dom_HTMLElement(zend_class_entry *class_entry_Dom_Element)
{
zend_class_entry ce, *class_entry;
INIT_NS_CLASS_ENTRY(ce, "Dom", "HTMLElement", class_Dom_HTMLElement_methods);
class_entry = zend_register_internal_class_ex(&ce, class_entry_Dom_Element);
return class_entry;
}
static zend_class_entry *register_class_Dom_Attr(zend_class_entry *class_entry_Dom_Node)
{
zend_class_entry ce, *class_entry;
@ -3445,15 +3459,15 @@ static zend_class_entry *register_class_Dom_Document(zend_class_entry *class_ent
zval property_body_default_value;
ZVAL_UNDEF(&property_body_default_value);
zend_string *property_body_name = zend_string_init("body", sizeof("body") - 1, 1);
zend_string *property_body_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1);
zend_declare_typed_property(class_entry, property_body_name, &property_body_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_body_class_Dom_Element, 0, MAY_BE_NULL));
zend_string *property_body_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1);
zend_declare_typed_property(class_entry, property_body_name, &property_body_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_body_class_Dom_HTMLElement, 0, MAY_BE_NULL));
zend_string_release(property_body_name);
zval property_head_default_value;
ZVAL_UNDEF(&property_head_default_value);
zend_string *property_head_name = zend_string_init("head", sizeof("head") - 1, 1);
zend_string *property_head_class_Dom_Element = zend_string_init("Dom\\Element", sizeof("Dom\\Element")-1, 1);
zend_declare_typed_property(class_entry, property_head_name, &property_head_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_head_class_Dom_Element, 0, MAY_BE_NULL));
zend_string *property_head_class_Dom_HTMLElement = zend_string_init("Dom\\HTMLElement", sizeof("Dom\\HTMLElement")-1, 1);
zend_declare_typed_property(class_entry, property_head_name, &property_head_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_CLASS(property_head_class_Dom_HTMLElement, 0, MAY_BE_NULL));
zend_string_release(property_head_name);
zval property_title_default_value;

View file

@ -11,7 +11,7 @@ function testNormalReplace($cb)
var_dump($dom->body?->nodeName);
try {
$dom->body = $cb($dom);
} catch (DOMException $e) {
} catch (Throwable $e) {
echo $e->getMessage(), "\n";
}
var_dump($dom->body?->nodeName);
@ -50,11 +50,11 @@ The new body must either be a body or a frameset tag
string(4) "BODY"
--- Right element tag in wrong namespace ---
string(4) "BODY"
The new body must either be a body or a frameset tag
Cannot assign Dom\Element to property Dom\Document::$body of type ?Dom\HTMLElement
string(4) "BODY"
--- Right element tag in no namespace ---
string(4) "BODY"
The new body must either be a body or a frameset tag
Cannot assign Dom\Element to property Dom\Document::$body of type ?Dom\HTMLElement
string(4) "BODY"
--- Set body without document element ---
A body can only be set if there is a document element

View file

@ -5,7 +5,7 @@ dom
--FILE--
<?php
class Custom extends Dom\Element {
class Custom extends Dom\HTMLElement {
public int $test = 1;
public function reverseTagName(): string {
@ -15,7 +15,7 @@ class Custom extends Dom\Element {
}
$dom = Dom\HTMLDocument::createFromString("<div>foo</div>", LIBXML_NOERROR);
$dom->registerNodeClass("Dom\\Element", "Custom");
$dom->registerNodeClass("Dom\\HTMLElement", "Custom");
var_dump($dom->getElementsByTagName('div')[0]->reverseTagName());

View file

@ -5,10 +5,10 @@ dom
--FILE--
<?php
class MyElement extends Dom\Element {}
class MyElement extends Dom\HTMLElement {}
$dom = Dom\HTMLDocument::createFromString("<p>foo</p>", LIBXML_NOERROR);
$dom->registerNodeClass("Dom\\Element", "MyElement");
$dom->registerNodeClass("Dom\\HTMLElement", "MyElement");
// Destroy reference to the DOM
$child = $dom->documentElement;

View file

@ -5,10 +5,10 @@ dom
--FILE--
<?php
class MyElement extends Dom\Element {}
class MyElement extends Dom\HTMLElement {}
$dom = Dom\HTMLDocument::createFromString("<p>foo</p>", LIBXML_NOERROR);
$dom->registerNodeClass("Dom\\Element", "MyElement");
$dom->registerNodeClass("Dom\\HTMLElement", "MyElement");
$child = $dom->documentElement->appendChild($dom->createElement('html'));
// Destroy reference to the DOM

View file

@ -14,5 +14,5 @@ try {
echo $dom->saveXml();
?>
--EXPECT--
Cannot modify readonly property Dom\Element::$prefix
Cannot modify readonly property Dom\HTMLElement::$prefix
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>