diff --git a/UPGRADING b/UPGRADING index 6a7a54f71745..acb2a163cdb2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -88,6 +88,9 @@ PHP 8.5 UPGRADE NOTES statement from the DEALLOCATE sql command in that we can reuse its name afterwards. +- Reflection: + . ReflectionConstant::getFileName() was introduced. + ======================================== 7. New Classes and Interfaces ======================================== diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index d453b8bb7371..9206eb8e1638 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -46,12 +46,18 @@ void free_zend_constant(zval *zv) if (c->name) { zend_string_release_ex(c->name, 0); } + if (c->filename) { + zend_string_release_ex(c->filename, 0); + } efree(c); } else { zval_internal_ptr_dtor(&c->value); if (c->name) { zend_string_release_ex(c->name, 1); } + if (c->filename) { + zend_string_release_ex(c->filename, 1); + } free(c); } } @@ -68,6 +74,9 @@ static void copy_zend_constant(zval *zv) c = Z_PTR_P(zv); c->name = zend_string_copy(c->name); + if (c->filename != NULL) { + c->filename = zend_string_copy(c->filename); + } if (Z_TYPE(c->value) == IS_STRING) { Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1); } @@ -495,6 +504,13 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) name = c->name; } + zend_string *filename = zend_get_executed_filename_ex(); + if (filename == NULL) { + c->filename = NULL; + } else { + c->filename = zend_string_copy(filename); + } + /* Check if the user is trying to define any special constant */ if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__") || (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name))) @@ -502,6 +518,10 @@ ZEND_API zend_result zend_register_constant(zend_constant *c) ) { zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name)); zend_string_release(c->name); + if (c->filename) { + zend_string_release(c->filename); + c->filename = NULL; + } if (!persistent) { zval_ptr_dtor_nogc(&c->value); } diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h index 6f0710c0ce63..fbefe0011ae1 100644 --- a/Zend/zend_constants.h +++ b/Zend/zend_constants.h @@ -33,6 +33,7 @@ typedef struct _zend_constant { zval value; zend_string *name; + zend_string *filename; } zend_constant; #define ZEND_CONSTANT_FLAGS(c) \ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index f42479cf745d..9ebc15f3a43f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -299,6 +299,9 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown) if (c->name) { zend_string_release_ex(c->name, 0); } + if (c->filename) { + zend_string_release_ex(c->filename, 0); + } efree(c); zend_string_release_ex(key, 0); } ZEND_HASH_MAP_FOREACH_END_DEL(); diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index a5562f165f76..fd3b883c3051 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -7835,6 +7835,20 @@ ZEND_METHOD(ReflectionConstant, isDeprecated) RETURN_BOOL(ZEND_CONSTANT_FLAGS(const_) & CONST_DEPRECATED); } +ZEND_METHOD(ReflectionConstant, getFileName) +{ + reflection_object *intern; + zend_constant *const_; + + ZEND_PARSE_PARAMETERS_NONE(); + + GET_REFLECTION_OBJECT_PTR(const_); + if (const_->filename != NULL) { + RETURN_STR_COPY(const_->filename); + } + RETURN_FALSE; +} + ZEND_METHOD(ReflectionConstant, __toString) { reflection_object *intern; diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index d9acc08d2242..399166d5e53f 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -914,5 +914,7 @@ public function getValue(): mixed {} public function isDeprecated(): bool {} + public function getFileName(): string|false {} + public function __toString(): string {} } diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index 92d80de5a60c..3a6c3b6ad835 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: 1cdf310b94e2297a4e426bd4c0c1ab4d5995936d */ + * Stub hash: 1412eb6e3b1093bbd4144985cca0796d30668dbb */ 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) @@ -703,6 +703,9 @@ ZEND_END_ARG_INFO() #define arginfo_class_ReflectionConstant_isDeprecated arginfo_class_ReflectionFunctionAbstract_hasTentativeReturnType +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_ReflectionConstant_getFileName, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_END_ARG_INFO() + #define arginfo_class_ReflectionConstant___toString arginfo_class_ReflectionFunction___toString ZEND_METHOD(Reflection, getModifierNames); @@ -968,6 +971,7 @@ ZEND_METHOD(ReflectionConstant, getNamespaceName); ZEND_METHOD(ReflectionConstant, getShortName); ZEND_METHOD(ReflectionConstant, getValue); ZEND_METHOD(ReflectionConstant, isDeprecated); +ZEND_METHOD(ReflectionConstant, getFileName); ZEND_METHOD(ReflectionConstant, __toString); static const zend_function_entry class_Reflection_methods[] = { @@ -1332,6 +1336,7 @@ static const zend_function_entry class_ReflectionConstant_methods[] = { ZEND_ME(ReflectionConstant, getShortName, arginfo_class_ReflectionConstant_getShortName, ZEND_ACC_PUBLIC) 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, __toString, arginfo_class_ReflectionConstant___toString, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/reflection/tests/ReflectionConstant_getFileName.phpt b/ext/reflection/tests/ReflectionConstant_getFileName.phpt new file mode 100644 index 000000000000..b627acceec4b --- /dev/null +++ b/ext/reflection/tests/ReflectionConstant_getFileName.phpt @@ -0,0 +1,44 @@ +--TEST-- +ReflectionConstant::getFileName() +--FILE-- +getFileName()); +} + +define('IN_CURRENT_FILE_DEFINED', 42); +const IN_CURRENT_FILE_AST = 123; + +echo "From PHP:\n"; +testConstant('PHP_VERSION'); +testConstant('STDIN'); +testConstant('STDOUT'); +testConstant('STDERR'); + +echo "\nFrom the current file:\n"; +testConstant('IN_CURRENT_FILE_DEFINED'); +testConstant('IN_CURRENT_FILE_AST'); + +echo "\nFrom an included file:\n"; +testConstant('INCLUDED_CONSTANT_DEFINED'); +testConstant('INCLUDED_CONSTANT_AST'); +?> +--EXPECTF-- +From PHP: +PHP_VERSION: bool(false) +STDIN: bool(false) +STDOUT: bool(false) +STDERR: bool(false) + +From the current file: +IN_CURRENT_FILE_DEFINED: string(%d) "%sReflectionConstant_getFileName.php" +IN_CURRENT_FILE_AST: string(%d) "%sReflectionConstant_getFileName.php" + +From an included file: +INCLUDED_CONSTANT_DEFINED: string(%d) "%sincluded5.inc" +INCLUDED_CONSTANT_AST: string(%d) "%sincluded5.inc" diff --git a/ext/reflection/tests/included5.inc b/ext/reflection/tests/included5.inc new file mode 100644 index 000000000000..d406ce0f0f6a --- /dev/null +++ b/ext/reflection/tests/included5.inc @@ -0,0 +1,5 @@ +