diff --git a/UPGRADING b/UPGRADING
index d8327ed93348..e7ddbae6b2cd 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -43,6 +43,8 @@ PHP 8.4 UPGRADE NOTES
. XSLTProcessor::setParameter() will now throw a ValueError when its arguments
contain null bytes. This never actually worked correctly in the first place,
which is why it throws an exception nowadays.
+ . The typed properties XSLTProcessor::$cloneDocument and
+ XSLTProcessor::$doXInclude are now declared.
========================================
2. New Features
diff --git a/ext/xsl/php_xsl.stub.php b/ext/xsl/php_xsl.stub.php
index 4bba5beae8c5..55ad36150bf6 100644
--- a/ext/xsl/php_xsl.stub.php
+++ b/ext/xsl/php_xsl.stub.php
@@ -71,6 +71,10 @@
class XSLTProcessor
{
+ public bool $doXInclude = false;
+
+ public bool $cloneDocument = false;
+
/**
* @param DOMDocument|SimpleXMLElement $stylesheet
* @tentative-return-type
diff --git a/ext/xsl/php_xsl_arginfo.h b/ext/xsl/php_xsl_arginfo.h
index aaa8531496a3..d1c23d4bfe6f 100644
--- a/ext/xsl/php_xsl_arginfo.h
+++ b/ext/xsl/php_xsl_arginfo.h
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 606e6ceba2381588b28e25e140fbcfec8a4dbe84 */
+ * Stub hash: 5518a63a4adec49c81e650d620ce2dbce41d8d65 */
ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_XSLTProcessor_importStylesheet, 0, 1, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, stylesheet, IS_OBJECT, 0)
@@ -113,5 +113,17 @@ static zend_class_entry *register_class_XSLTProcessor(void)
INIT_CLASS_ENTRY(ce, "XSLTProcessor", class_XSLTProcessor_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
+ zval property_doXInclude_default_value;
+ ZVAL_FALSE(&property_doXInclude_default_value);
+ zend_string *property_doXInclude_name = zend_string_init("doXInclude", sizeof("doXInclude") - 1, 1);
+ zend_declare_typed_property(class_entry, property_doXInclude_name, &property_doXInclude_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
+ zend_string_release(property_doXInclude_name);
+
+ zval property_cloneDocument_default_value;
+ ZVAL_FALSE(&property_cloneDocument_default_value);
+ zend_string *property_cloneDocument_name = zend_string_init("cloneDocument", sizeof("cloneDocument") - 1, 1);
+ zend_declare_typed_property(class_entry, property_cloneDocument_name, &property_cloneDocument_default_value, ZEND_ACC_PUBLIC, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_BOOL));
+ zend_string_release(property_cloneDocument_name);
+
return class_entry;
}
diff --git a/ext/xsl/tests/cloneDocument.phpt b/ext/xsl/tests/cloneDocument.phpt
new file mode 100644
index 000000000000..0af1da4c6e35
--- /dev/null
+++ b/ext/xsl/tests/cloneDocument.phpt
@@ -0,0 +1,45 @@
+--TEST--
+cloneDocument
+--EXTENSIONS--
+xsl
+dom
+--FILE--
+loadXML('hello');
+
+function test() {
+ global $xml;
+ $xml->documentElement->firstChild->textContent = "bye";
+}
+
+$xsl = new DOMDocument;
+$xsl->loadXML(<<
+
+
+
+
+
+
+XML);
+
+$xslt = new XSLTProcessor;
+$xslt->registerPHPFunctions();
+$xslt->cloneDocument = true;
+$xslt->importStylesheet($xsl);
+echo $xslt->transformToXml($xml);
+
+$xslt = new XSLTProcessor;
+$xslt->registerPHPFunctions();
+$xslt->cloneDocument = false;
+$xslt->importStylesheet($xsl);
+echo $xslt->transformToXml($xml);
+
+?>
+--EXPECT--
+
+hello
+
+bye
diff --git a/ext/xsl/tests/xinclude/data.xml b/ext/xsl/tests/xinclude/data.xml
new file mode 100644
index 000000000000..7c2ef1f6bff3
--- /dev/null
+++ b/ext/xsl/tests/xinclude/data.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/ext/xsl/tests/xinclude/xinclude.phpt b/ext/xsl/tests/xinclude/xinclude.phpt
new file mode 100644
index 000000000000..33f9565bcf81
--- /dev/null
+++ b/ext/xsl/tests/xinclude/xinclude.phpt
@@ -0,0 +1,41 @@
+--TEST--
+doXInclude
+--EXTENSIONS--
+xsl
+dom
+--FILE--
+loadXML('');
+
+$xsl = new DOMDocument;
+$xsl->loadXML(<<
+
+
+
+
+
+
+
+XML);
+
+$xslt = new XSLTProcessor;
+$xslt->doXInclude = true;
+$xslt->importStylesheet($xsl);
+echo $xslt->transformToXml($xml);
+
+$xslt = new XSLTProcessor;
+$xslt->doXInclude = false;
+$xslt->importStylesheet($xsl);
+echo $xslt->transformToXml($xml);
+
+?>
+--EXPECT--
+
+This is sample content
+
+
diff --git a/ext/xsl/tests/xinclude/xincluded.xml b/ext/xsl/tests/xinclude/xincluded.xml
new file mode 100644
index 000000000000..cdca87bad7e3
--- /dev/null
+++ b/ext/xsl/tests/xinclude/xincluded.xml
@@ -0,0 +1,2 @@
+
+This is sample content
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index fb607c40b1a1..25a30b64c027 100644
--- a/ext/xsl/xsltprocessor.c
+++ b/ext/xsl/xsltprocessor.c
@@ -313,11 +313,8 @@ PHP_METHOD(XSLTProcessor, importStylesheet)
intern = Z_XSL_P(id);
member = ZSTR_INIT_LITERAL("cloneDocument", 0);
- cloneDocu = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_IS, NULL, &rv);
- if (Z_TYPE_P(cloneDocu) != IS_NULL) {
- convert_to_long(cloneDocu);
- clone_docu = Z_LVAL_P(cloneDocu);
- }
+ cloneDocu = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv);
+ clone_docu = zend_is_true(cloneDocu);
zend_string_release_ex(member, 0);
if (clone_docu == 0) {
/* check if the stylesheet is using xsl:key, if yes, we have to clone the document _always_ before a transformation */
@@ -415,11 +412,8 @@ static xmlDocPtr php_xsl_apply_stylesheet(zval *id, xsl_object *intern, xsltStyl
}
member = ZSTR_INIT_LITERAL("doXInclude", 0);
- doXInclude = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_IS, NULL, &rv);
- if (Z_TYPE_P(doXInclude) != IS_NULL) {
- convert_to_long(doXInclude);
- ctxt->xinclude = Z_LVAL_P(doXInclude);
- }
+ doXInclude = zend_std_read_property(Z_OBJ_P(id), member, BP_VAR_R, NULL, &rv);
+ ctxt->xinclude = zend_is_true(doXInclude);
zend_string_release_ex(member, 0);
secPrefsValue = intern->securityPrefs;