From 59949e315ee7c10a4a800b4a64a5697fb7d88002 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 25 Oct 2024 12:09:00 -0700 Subject: [PATCH] Add `ReflectionConstant::getExtension()` and `::getExtensionName()` --- UPGRADING | 2 + ext/reflection/php_reflection.c | 73 +++++++++++++++++-- ext/reflection/php_reflection.stub.php | 4 + ext/reflection/php_reflection_arginfo.h | 11 ++- .../ReflectionConstant_getExtension.phpt | 32 ++++++++ .../ReflectionConstant_getExtensionName.phpt | 26 +++++++ 6 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 ext/reflection/tests/ReflectionConstant_getExtension.phpt create mode 100644 ext/reflection/tests/ReflectionConstant_getExtensionName.phpt diff --git a/UPGRADING b/UPGRADING index 07cee36eb425..0c6a8d4c43e2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -90,6 +90,8 @@ PHP 8.5 UPGRADE NOTES - Reflection: . ReflectionConstant::getFileName() was introduced. + . ReflectionConstant::getExtension() and + ReflectionConstant::getExtensionName() were introduced. ======================================== 7. New Classes and Interfaces diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index a76d8da60679..1d76c5714106 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -1319,10 +1319,21 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object) } /* }}} */ +/* {{{ reflection_extension_factory_ex */ +static void reflection_extension_factory_ex(zval *object, zend_module_entry *module) +{ + reflection_instantiate(reflection_extension_ptr, object); + reflection_object *intern = Z_REFLECTION_P(object); + intern->ptr = module; + intern->ref_type = REF_TYPE_OTHER; + intern->ce = NULL; + ZVAL_STRING(reflection_prop_name(object), module->name); +} +/* }}} */ + /* {{{ reflection_extension_factory */ static void reflection_extension_factory(zval *object, const char *name_str) { - reflection_object *intern; size_t name_len = strlen(name_str); zend_string *lcname; struct _zend_module_entry *module; @@ -1335,12 +1346,7 @@ static void reflection_extension_factory(zval *object, const char *name_str) return; } - reflection_instantiate(reflection_extension_ptr, object); - intern = Z_REFLECTION_P(object); - intern->ptr = module; - intern->ref_type = REF_TYPE_OTHER; - intern->ce = NULL; - ZVAL_STRINGL(reflection_prop_name(object), module->name, name_len); + reflection_extension_factory_ex(object, module); } /* }}} */ @@ -7567,6 +7573,59 @@ ZEND_METHOD(ReflectionConstant, getFileName) RETURN_FALSE; } +static void reflection_constant_find_ext(INTERNAL_FUNCTION_PARAMETERS, bool only_name) +{ + reflection_object *intern; + zend_constant *const_; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(const_); + int module_number = ZEND_CONSTANT_MODULE_NUMBER(const_); + if (module_number == PHP_USER_CONSTANT) { + // For user constants, ReflectionConstant::getExtension() returns null, + // ReflectionConstant::getExtensionName() returns false + if (only_name) { + RETURN_FALSE; + } + RETURN_NULL(); + } + zend_module_entry *module; + ZEND_HASH_MAP_FOREACH_PTR(&module_registry, module) { + if (module->module_number != module_number) { + continue; + } + if (only_name) { + RETURN_STRING(module->name); + } + reflection_extension_factory_ex(return_value, module); + return; + } ZEND_HASH_FOREACH_END(); + + zend_throw_exception_ex( + reflection_exception_ptr, + 0, + "Unable to locate extension with module_number %d that provides constant %s", + module_number, + ZSTR_VAL(const_->name) + ); + RETURN_THROWS(); +} + +/* {{{ Returns NULL or the extension the constant belongs to */ +ZEND_METHOD(ReflectionConstant, getExtension) +{ + reflection_constant_find_ext(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); +} +/* }}} */ + +/* {{{ Returns false or the name of the extension the constant belongs to */ +ZEND_METHOD(ReflectionConstant, getExtensionName) +{ + reflection_constant_find_ext(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); +} +/* }}} */ + ZEND_METHOD(ReflectionConstant, __toString) { reflection_object *intern; diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index eb64f0de72b4..de15e405c732 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -918,5 +918,9 @@ public function isDeprecated(): bool {} public function getFileName(): string|false {} + public function getExtension(): ?ReflectionExtension {} + + public function getExtensionName(): string|false {} + public function __toString(): string {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 6ad146c6ef9d..6cdadc5c5b30 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 603181d7e1d8292ef694913d4495d3cbb9dd7798 */ + * Stub hash: dbb59b2dd53c2849f66c00ce12228ebb07f50773 */ ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_Reflection_getModifierNames, 0, 1, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO(0, modifiers, IS_LONG, 0) @@ -708,6 +708,11 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_ReflectionConstant_getFileName, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_ReflectionConstant_getExtension, 0, 0, ReflectionExtension, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_ReflectionConstant_getExtensionName arginfo_class_ReflectionConstant_getFileName + #define arginfo_class_ReflectionConstant___toString arginfo_class_ReflectionFunction___toString ZEND_METHOD(Reflection, getModifierNames); @@ -975,6 +980,8 @@ ZEND_METHOD(ReflectionConstant, getShortName); ZEND_METHOD(ReflectionConstant, getValue); ZEND_METHOD(ReflectionConstant, isDeprecated); ZEND_METHOD(ReflectionConstant, getFileName); +ZEND_METHOD(ReflectionConstant, getExtension); +ZEND_METHOD(ReflectionConstant, getExtensionName); ZEND_METHOD(ReflectionConstant, __toString); static const zend_function_entry class_Reflection_methods[] = { @@ -1341,6 +1348,8 @@ static const zend_function_entry class_ReflectionConstant_methods[] = { ZEND_ME(ReflectionConstant, getValue, arginfo_class_ReflectionConstant_getValue, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, isDeprecated, arginfo_class_ReflectionConstant_isDeprecated, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, getFileName, arginfo_class_ReflectionConstant_getFileName, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionConstant, getExtension, arginfo_class_ReflectionConstant_getExtension, ZEND_ACC_PUBLIC) + ZEND_ME(ReflectionConstant, getExtensionName, arginfo_class_ReflectionConstant_getExtensionName, ZEND_ACC_PUBLIC) ZEND_ME(ReflectionConstant, __toString, arginfo_class_ReflectionConstant___toString, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/reflection/tests/ReflectionConstant_getExtension.phpt b/ext/reflection/tests/ReflectionConstant_getExtension.phpt new file mode 100644 index 000000000000..9cc010461dc5 --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getExtension.phpt @@ -0,0 +1,32 @@ +--TEST-- +ReflectionConstant::getExtension() +--EXTENSIONS-- +json +--FILE-- +getExtension()); + +$reflectionConstant = new ReflectionConstant('JSON_ERROR_NONE'); +var_dump($reflectionConstant->getExtension()); + +const CT_CONST = 5; +$reflectionConstant = new ReflectionConstant('CT_CONST'); +var_dump($reflectionConstant->getExtension()); + +define('RT_CONST', 6); +$reflectionConstant = new ReflectionConstant('RT_CONST'); +var_dump($reflectionConstant->getExtension()); +?> +--EXPECTF-- +object(ReflectionExtension)#%d (1) { + ["name"]=> + string(4) "Core" +} +object(ReflectionExtension)#%d (1) { + ["name"]=> + string(4) "json" +} +NULL +NULL diff --git a/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt b/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt new file mode 100644 index 000000000000..dc4322dce4ab --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getExtensionName.phpt @@ -0,0 +1,26 @@ +--TEST-- +ReflectionConstant::getExtensionName() +--EXTENSIONS-- +json +--FILE-- +getExtensionName()); + +$reflectionConstant = new ReflectionConstant('JSON_ERROR_NONE'); +var_dump($reflectionConstant->getExtensionName()); + +const CT_CONST = 5; +$reflectionConstant = new ReflectionConstant('CT_CONST'); +var_dump($reflectionConstant->getExtensionName()); + +define('RT_CONST', 6); +$reflectionConstant = new ReflectionConstant('RT_CONST'); +var_dump($reflectionConstant->getExtensionName()); +?> +--EXPECT-- +string(4) "Core" +string(4) "json" +bool(false) +bool(false)