Skip to content

Commit dc93209

Browse files
GH-15723: add ReflectionConstant::getFileName()
Allow determining the name of the file that defined a constant, when the constant was defined in userland code via `define()`. For constants defined by PHP core or extensions, `false` is returned, matching the existing `getFileName()` methods on other reflection classes.
1 parent 1b9568d commit dc93209

9 files changed

+76
-1
lines changed

Zend/zend_builtin_functions.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,13 @@ ZEND_FUNCTION(define)
549549
/* non persistent */
550550
ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
551551
c.name = zend_string_copy(name);
552+
553+
zend_string *filename = zend_get_executed_filename_ex();
554+
if (filename == NULL) {
555+
c.filename = NULL;
556+
} else {
557+
c.filename = zend_string_copy(filename);
558+
}
552559
if (zend_register_constant(&c) == SUCCESS) {
553560
RETURN_TRUE;
554561
} else {

Zend/zend_constants.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@ void free_zend_constant(zval *zv)
4646
if (c->name) {
4747
zend_string_release_ex(c->name, 0);
4848
}
49+
if (c->filename) {
50+
zend_string_release_ex(c->filename, 0);
51+
}
4952
efree(c);
5053
} else {
5154
zval_internal_ptr_dtor(&c->value);
5255
if (c->name) {
5356
zend_string_release_ex(c->name, 1);
5457
}
58+
if (c->filename) {
59+
zend_string_release_ex(c->filename, 1);
60+
}
5561
free(c);
5662
}
5763
}
@@ -68,6 +74,9 @@ static void copy_zend_constant(zval *zv)
6874

6975
c = Z_PTR_P(zv);
7076
c->name = zend_string_copy(c->name);
77+
if (c->filename != NULL) {
78+
c->filename = zend_string_copy(c->filename);
79+
}
7180
if (Z_TYPE(c->value) == IS_STRING) {
7281
Z_STR(c->value) = zend_string_dup(Z_STR(c->value), 1);
7382
}
@@ -123,6 +132,7 @@ ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int
123132
ZVAL_NULL(&c.value);
124133
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
125134
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
135+
c.filename = NULL;
126136
zend_register_constant(&c);
127137
}
128138

@@ -133,6 +143,7 @@ ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, boo
133143
ZVAL_BOOL(&c.value, bval);
134144
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
135145
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
146+
c.filename = NULL;
136147
zend_register_constant(&c);
137148
}
138149

@@ -143,6 +154,7 @@ ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zen
143154
ZVAL_LONG(&c.value, lval);
144155
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
145156
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
157+
c.filename = NULL;
146158
zend_register_constant(&c);
147159
}
148160

@@ -154,6 +166,7 @@ ZEND_API void zend_register_double_constant(const char *name, size_t name_len, d
154166
ZVAL_DOUBLE(&c.value, dval);
155167
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
156168
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
169+
c.filename = NULL;
157170
zend_register_constant(&c);
158171
}
159172

@@ -165,6 +178,7 @@ ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len,
165178
ZVAL_STR(&c.value, zend_string_init_interned(strval, strlen, flags & CONST_PERSISTENT));
166179
ZEND_CONSTANT_SET_FLAGS(&c, flags, module_number);
167180
c.name = zend_string_init_interned(name, name_len, flags & CONST_PERSISTENT);
181+
c.filename = NULL;
168182
zend_register_constant(&c);
169183
}
170184

@@ -502,6 +516,10 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
502516
) {
503517
zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name));
504518
zend_string_release(c->name);
519+
if (c->filename) {
520+
zend_string_release(c->filename);
521+
c->filename = NULL;
522+
}
505523
if (!persistent) {
506524
zval_ptr_dtor_nogc(&c->value);
507525
}

Zend/zend_constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
typedef struct _zend_constant {
3434
zval value;
3535
zend_string *name;
36+
zend_string *filename;
3637
} zend_constant;
3738

3839
#define ZEND_CONSTANT_FLAGS(c) \

Zend/zend_execute_API.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,9 @@ ZEND_API void zend_shutdown_executor_values(bool fast_shutdown)
299299
if (c->name) {
300300
zend_string_release_ex(c->name, 0);
301301
}
302+
if (c->filename) {
303+
zend_string_release_ex(c->filename, 0);
304+
}
302305
efree(c);
303306
zend_string_release_ex(key, 0);
304307
} ZEND_HASH_MAP_FOREACH_END_DEL();

ext/reflection/php_reflection.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7824,6 +7824,20 @@ ZEND_METHOD(ReflectionConstant, isDeprecated)
78247824
RETURN_BOOL(ZEND_CONSTANT_FLAGS(const_) & CONST_DEPRECATED);
78257825
}
78267826

7827+
ZEND_METHOD(ReflectionConstant, getFileName)
7828+
{
7829+
reflection_object *intern;
7830+
zend_constant *const_;
7831+
7832+
ZEND_PARSE_PARAMETERS_NONE();
7833+
7834+
GET_REFLECTION_OBJECT_PTR(const_);
7835+
if (const_->filename != NULL) {
7836+
RETURN_STR_COPY(const_->filename);
7837+
}
7838+
RETURN_FALSE;
7839+
}
7840+
78277841
ZEND_METHOD(ReflectionConstant, __toString)
78287842
{
78297843
reflection_object *intern;

ext/reflection/php_reflection.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,5 +918,7 @@ public function getValue(): mixed {}
918918

919919
public function isDeprecated(): bool {}
920920

921+
public function getFileName(): string|false {}
922+
921923
public function __toString(): string {}
922924
}

ext/reflection/php_reflection_arginfo.h

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
ReflectionConstant::getFileName()
3+
--FILE--
4+
<?php
5+
6+
include "included5.inc";
7+
8+
$reflectionConstant = new ReflectionConstant('PHP_VERSION');
9+
var_dump($reflectionConstant->getFileName());
10+
11+
define('IN_CURRENT_FILE', 42);
12+
$reflectionConstant = new ReflectionConstant('IN_CURRENT_FILE');
13+
var_dump($reflectionConstant->getFileName());
14+
15+
$reflectionConstant = new ReflectionConstant('INCLUDED_CONSTANT');
16+
var_dump($reflectionConstant->getFileName());
17+
18+
?>
19+
--EXPECTF--
20+
bool(false)
21+
string(%d) "%sReflectionConstant_getFileName.php"
22+
string(%d) "%sincluded5.inc"

ext/reflection/tests/included5.inc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
define('INCLUDED_CONSTANT', 'Foo');
3+
?>

0 commit comments

Comments
 (0)