Skip to content

Commit f5e743a

Browse files
DanielEScherzeriluuu1994
authored andcommitted
Add ReflectionConstant::getFileName()
Allow determining the name of the file that defined a constant, when the constant was defined in userland code via const or define(). For constants defined by PHP core or extensions, false is returned, matching the existing getFileName() methods on other reflection classes. Fixes phpGH-15723 Closes phpGH-15847
1 parent 94ac1cd commit f5e743a

9 files changed

+98
-1
lines changed

UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ PHP 8.5 UPGRADE NOTES
8888
statement from the DEALLOCATE sql command in that we can reuse
8989
its name afterwards.
9090

91+
- Reflection:
92+
. ReflectionConstant::getFileName() was introduced.
93+
9194
========================================
9295
7. New Classes and Interfaces
9396
========================================

Zend/zend_constants.c

+20
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
}
@@ -495,13 +504,24 @@ ZEND_API zend_result zend_register_constant(zend_constant *c)
495504
name = c->name;
496505
}
497506

507+
zend_string *filename = zend_get_executed_filename_ex();
508+
if (filename == NULL) {
509+
c->filename = NULL;
510+
} else {
511+
c->filename = zend_string_copy(filename);
512+
}
513+
498514
/* Check if the user is trying to define any special constant */
499515
if (zend_string_equals_literal(name, "__COMPILER_HALT_OFFSET__")
500516
|| (!persistent && zend_get_special_const(ZSTR_VAL(name), ZSTR_LEN(name)))
501517
|| zend_hash_add_constant(EG(zend_constants), name, c) == NULL
502518
) {
503519
zend_error(E_WARNING, "Constant %s already defined", ZSTR_VAL(name));
504520
zend_string_release(c->name);
521+
if (c->filename) {
522+
zend_string_release(c->filename);
523+
c->filename = NULL;
524+
}
505525
if (!persistent) {
506526
zval_ptr_dtor_nogc(&c->value);
507527
}

Zend/zend_constants.h

+1
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

+3
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

+14
Original file line numberDiff line numberDiff line change
@@ -7553,6 +7553,20 @@ ZEND_METHOD(ReflectionConstant, isDeprecated)
75537553
RETURN_BOOL(ZEND_CONSTANT_FLAGS(const_) & CONST_DEPRECATED);
75547554
}
75557555

7556+
ZEND_METHOD(ReflectionConstant, getFileName)
7557+
{
7558+
reflection_object *intern;
7559+
zend_constant *const_;
7560+
7561+
ZEND_PARSE_PARAMETERS_NONE();
7562+
7563+
GET_REFLECTION_OBJECT_PTR(const_);
7564+
if (const_->filename != NULL) {
7565+
RETURN_STR_COPY(const_->filename);
7566+
}
7567+
RETURN_FALSE;
7568+
}
7569+
75567570
ZEND_METHOD(ReflectionConstant, __toString)
75577571
{
75587572
reflection_object *intern;

ext/reflection/php_reflection.stub.php

+2
Original file line numberDiff line numberDiff line change
@@ -916,5 +916,7 @@ public function getValue(): mixed {}
916916

917917
public function isDeprecated(): bool {}
918918

919+
public function getFileName(): string|false {}
920+
919921
public function __toString(): string {}
920922
}

ext/reflection/php_reflection_arginfo.h

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--TEST--
2+
ReflectionConstant::getFileName()
3+
--FILE--
4+
<?php
5+
6+
include "included5.inc";
7+
8+
function testConstant(string $name): void {
9+
$ref = new ReflectionConstant($name);
10+
echo "$name: ";
11+
var_dump($ref->getFileName());
12+
}
13+
14+
define('IN_CURRENT_FILE_DEFINED', 42);
15+
const IN_CURRENT_FILE_AST = 123;
16+
17+
echo "From PHP:\n";
18+
testConstant('PHP_VERSION');
19+
testConstant('STDIN');
20+
testConstant('STDOUT');
21+
testConstant('STDERR');
22+
23+
echo "\nFrom the current file:\n";
24+
testConstant('IN_CURRENT_FILE_DEFINED');
25+
testConstant('IN_CURRENT_FILE_AST');
26+
27+
echo "\nFrom an included file:\n";
28+
testConstant('INCLUDED_CONSTANT_DEFINED');
29+
testConstant('INCLUDED_CONSTANT_AST');
30+
?>
31+
--EXPECTF--
32+
From PHP:
33+
PHP_VERSION: bool(false)
34+
STDIN: bool(false)
35+
STDOUT: bool(false)
36+
STDERR: bool(false)
37+
38+
From the current file:
39+
IN_CURRENT_FILE_DEFINED: string(%d) "%sReflectionConstant_getFileName.php"
40+
IN_CURRENT_FILE_AST: string(%d) "%sReflectionConstant_getFileName.php"
41+
42+
From an included file:
43+
INCLUDED_CONSTANT_DEFINED: string(%d) "%sincluded5.inc"
44+
INCLUDED_CONSTANT_AST: string(%d) "%sincluded5.inc"

ext/reflection/tests/included5.inc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
define('INCLUDED_CONSTANT_DEFINED', 'Foo');
3+
4+
const INCLUDED_CONSTANT_AST = 'Bar';
5+
?>

0 commit comments

Comments
 (0)