diff options
author | Olly Betts <olly@survex.com> | 2022-09-29 18:14:23 +1300 |
---|---|---|
committer | Olly Betts <olly@survex.com> | 2022-09-29 18:16:51 +1300 |
commit | 9a4dea06c81448f86187c115912b4062ad1b3031 (patch) | |
tree | 05d73ec5f32114fc331d21b88ab76111887b320c | |
parent | 20ed76a27b9419cb7e07c1a4adb444a087555fb4 (diff) | |
download | swig-9a4dea06c81448f86187c115912b4062ad1b3031.tar.gz |
[php] Add php:allowdynamicproperties feature
This follows PHP 8.2 deprecating dynamic features.
The new feature also provides a clean way to fix the remaining PHP
test case failure under PHP 8.2.
-rw-r--r-- | CHANGES.current | 23 | ||||
-rw-r--r-- | Doc/Manual/Php.html | 48 | ||||
-rw-r--r-- | Examples/test-suite/cpp_basic.i | 2 | ||||
-rw-r--r-- | Source/Modules/php.cxx | 17 |
4 files changed, 86 insertions, 4 deletions
diff --git a/CHANGES.current b/CHANGES.current index 6df9d6c5f..bbdcdfb3b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,29 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 4.1.0 (in progress) =========================== +2022-09-29: olly + [PHP] Dynamic class properties are no longer supported by default. + + Historically PHP has supported dynamic class properties and SWIG + has implemented them too (because we implement the magic __get(), + __set() and __isset() methods we need to include explicit + handling). + + PHP 8.2 deprecates dynamic class properties - initially they'll + warn, and apparently they'll not work by default in PHP 9.0: + https://wiki.php.net/rfc/deprecate_dynamic_properties + + In PHP code dynamic properties can be enabled for a class by + marking that class with the attribute `#[AllowDynamicProperties]`. + + To follow this PHP change, in SWIG you now need to specify + `%feature("php:allowdynamicproperties", 1) Foo;` (or + `%feature("php:allowdynamicproperties", 1)` to enable it for + all wrapped classes). Unknown features are ignored, so you can add + it unconditionally and it'll work with older SWIG too. + + *** POTENTIAL INCOMPATIBILITY *** + 2022-09-19: wsfulton #1484 Fixes for class inheritance with the same name in different namespaces such as: diff --git a/Doc/Manual/Php.html b/Doc/Manual/Php.html index 72c914656..49d0474f7 100644 --- a/Doc/Manual/Php.html +++ b/Doc/Manual/Php.html @@ -30,6 +30,7 @@ <li><a href="#Php_nn2_6_3">Static Member Variables</a> <li><a href="#Php_nn2_6_4">Static Member Functions</a> <li><a href="#Php_nn2_6_5">Specifying Implemented Interfaces</a> +<li><a href="#Php_nn2_6_6">Dynamic Properties</a> </ul> <li><a href="#Php_nn2_7">PHP Pragmas, Startup and Shutdown code</a> </ul> @@ -843,6 +844,53 @@ so: If there are multiple interfaces, just list them separated by commas. </p> + +<H4><a name="Php_nn2_6_6">32.2.6.6 Dynamic Properties</a></H4> + + +<p> +Historically PHP has supported dynamic class properties and SWIG +has implemented them too (because we implement the magic <tt>__get()</tt>, +<tt>__set()</tt> and <tt>__isset()</tt> methods we need to include explicit +handling). +</p> + +<p> +PHP 8.2 <a +href="https://wiki.php.net/rfc/deprecate_dynamic_properties">deprecates +dynamic class properties</a> - initially they'll warn, and apparently they'll +not work by default in PHP 9.0. +</p> + +<p> +In PHP code dynamic properties can be enabled for a class by +marking that class with the attribute <tt>#[AllowDynamicProperties]</tt>. +</p> + +<p> +To follow this PHP change, as of SWIG 4.1.0 you now need enable dynamic +properties for any classes you want to support them. To enable for class +<tt>Foo</tt>: +</p> + +<div class="code"><pre> +%feature("php:allowdynamicproperties", 1) Foo; +</pre></div> + +<p> +or to enable them for all wrapped classes: +</p> + +<div class="code"><pre> +%feature("php:allowdynamicproperties", 1); +</pre></div> + +<p> +Note that unknown features are ignored, so you can add use these +unconditionally in your interface file and it'll work with older SWIG too. +</p> + + <H3><a name="Php_nn2_7">32.2.7 PHP Pragmas, Startup and Shutdown code</a></H3> diff --git a/Examples/test-suite/cpp_basic.i b/Examples/test-suite/cpp_basic.i index c39206b13..8c31a9cf0 100644 --- a/Examples/test-suite/cpp_basic.i +++ b/Examples/test-suite/cpp_basic.i @@ -4,6 +4,8 @@ %warnfilter(SWIGWARN_RUBY_WRONG_NAME) global_cint; /* Ruby, wrong constant name */ +%feature("php:allowdynamicproperties", 1) Foo; /* Allow PHP-specific custom property testing in _runme.php */ + %module cpp_basic %newobject Bar::testFoo; diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx index 3f12c0448..e6b9e991a 100644 --- a/Source/Modules/php.cxx +++ b/Source/Modules/php.cxx @@ -1056,12 +1056,12 @@ public: " if (director) director->swig_disown();\n", "}\n", NIL); } - Printf(f->code, "} else {\n"); if (swig_base) { - Printf(f->code, "PHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n}\n", prefix, swig_base); - } else { - Printf(f->code, "add_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n}\n"); + Printf(f->code, "} else {\nPHP_MN(%s%s___set)(INTERNAL_FUNCTION_PARAM_PASSTHRU);\n", prefix, swig_base); + } else if (Getattr(class_node, "feature:php:allowdynamicproperties")) { + Printf(f->code, "} else {\nadd_property_zval_ex(ZEND_THIS, ZSTR_VAL(arg2), ZSTR_LEN(arg2), &args[1]);\n"); } + Printf(f->code, "}\n"); Printf(f->code, "fail:\n"); Printf(f->code, "return;\n"); @@ -1777,6 +1777,15 @@ public: if (Getattr(n, "abstracts") && !GetFlag(n, "feature:notabstract")) { Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;\n", class_name); } + if (Getattr(n, "feature:php:allowdynamicproperties")) { + Append(s_oinit, "#ifdef ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES\n"); + Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES;\n", class_name); + Append(s_oinit, "#endif\n"); + } else { + Append(s_oinit, "#ifdef ZEND_ACC_NO_DYNAMIC_PROPERTIES\n"); + Printf(s_oinit, " SWIG_Php_ce_%s->ce_flags |= ZEND_ACC_NO_DYNAMIC_PROPERTIES;\n", class_name); + Append(s_oinit, "#endif\n"); + } String *swig_wrapped = swig_wrapped_interface_ce(); Printv(s_oinit, " zend_do_implement_interface(SWIG_Php_ce_", class_name, ", &", swig_wrapped, ");\n", NIL); |