summaryrefslogtreecommitdiff
path: root/ext/reflection/php_reflection.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/reflection/php_reflection.c')
-rw-r--r--ext/reflection/php_reflection.c485
1 files changed, 358 insertions, 127 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 64c5355fc8..280b3fc06c 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -43,12 +43,13 @@
#include "zend_extensions.h"
#include "zend_builtin_functions.h"
#include "zend_smart_str.h"
+#include "zend_enum.h"
#include "php_reflection_arginfo.h"
/* Key used to avoid leaking addresses in ReflectionProperty::getId() */
#define REFLECTION_KEY_LEN 16
ZEND_BEGIN_MODULE_GLOBALS(reflection)
- zend_bool key_initialized;
+ bool key_initialized;
unsigned char key[REFLECTION_KEY_LEN];
ZEND_END_MODULE_GLOBALS(reflection)
ZEND_DECLARE_MODULE_GLOBALS(reflection)
@@ -87,6 +88,9 @@ PHPAPI zend_class_entry *reflection_extension_ptr;
PHPAPI zend_class_entry *reflection_zend_extension_ptr;
PHPAPI zend_class_entry *reflection_reference_ptr;
PHPAPI zend_class_entry *reflection_attribute_ptr;
+PHPAPI zend_class_entry *reflection_enum_ptr;
+PHPAPI zend_class_entry *reflection_enum_unit_case_ptr;
+PHPAPI zend_class_entry *reflection_enum_backed_case_ptr;
/* Exception throwing macro */
#define _DO_THROW(msg) \
@@ -125,7 +129,7 @@ typedef struct _property_reference {
/* Struct for parameters */
typedef struct _parameter_reference {
uint32_t offset;
- zend_bool required;
+ bool required;
struct _zend_arg_info *arg_info;
zend_function *fptr;
} parameter_reference;
@@ -134,7 +138,7 @@ typedef struct _parameter_reference {
typedef struct _type_reference {
zend_type type;
/* Whether to use backwards compatible null representation */
- zend_bool legacy_behavior;
+ bool legacy_behavior;
} type_reference;
/* Struct for attributes */
@@ -180,7 +184,7 @@ static zend_always_inline uint32_t prop_get_flags(property_reference *ref) {
return ref->prop ? ref->prop->flags : ZEND_ACC_PUBLIC;
}
-static inline zend_bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
+static inline bool is_closure_invoke(zend_class_entry *ce, zend_string *lcname) {
return ce == zend_ce_closure
&& zend_string_equals_literal(lcname, ZEND_INVOKE_FUNC_NAME);
}
@@ -386,7 +390,7 @@ static void _class_string(smart_str *str, zend_class_entry *ce, zval *obj, char
zend_string *key;
zend_class_constant *c;
- ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, c) {
_class_const_string(str, ZSTR_VAL(key), c, ZSTR_VAL(sub_indent));
if (UNEXPECTED(EG(exception))) {
zend_string_release(sub_indent);
@@ -573,6 +577,9 @@ static void _class_const_string(smart_str *str, char *name, zend_class_constant
if (Z_TYPE(c->value) == IS_ARRAY) {
smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Array }\n",
indent, visibility, type, name);
+ } else if (Z_TYPE(c->value) == IS_OBJECT) {
+ smart_str_append_printf(str, "%sConstant [ %s %s %s ] { Object }\n",
+ indent, visibility, type, name);
} else {
zend_string *tmp_value_str;
zend_string *value_str = zval_get_tmp_string(&c->value, &tmp_value_str);
@@ -645,13 +652,13 @@ static int format_default_value(smart_str *str, zval *value, zend_class_entry *s
return SUCCESS;
}
-static inline zend_bool has_internal_arg_info(const zend_function *fptr) {
+static inline bool has_internal_arg_info(const zend_function *fptr) {
return fptr->type == ZEND_INTERNAL_FUNCTION
&& !(fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO);
}
/* {{{ _parameter_string */
-static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, char* indent)
+static void _parameter_string(smart_str *str, zend_function *fptr, struct _zend_arg_info *arg_info, uint32_t offset, bool required, char* indent)
{
smart_str_append_printf(str, "Parameter #%d [ ", offset);
if (!required) {
@@ -1251,6 +1258,18 @@ PHPAPI void zend_reflection_class_factory(zend_class_entry *ce, zval *object)
}
/* }}} */
+static void zend_reflection_enum_factory(zend_class_entry *ce, zval *object)
+{
+ reflection_object *intern;
+
+ reflection_instantiate(reflection_enum_ptr, object);
+ intern = Z_REFLECTION_P(object);
+ intern->ptr = ce;
+ intern->ref_type = REF_TYPE_OTHER;
+ intern->ce = ce;
+ ZVAL_STR_COPY(reflection_prop_name(object), ce->name);
+}
+
/* {{{ reflection_extension_factory */
static void reflection_extension_factory(zval *object, const char *name_str)
{
@@ -1277,7 +1296,7 @@ static void reflection_extension_factory(zval *object, const char *name_str)
/* }}} */
/* {{{ reflection_parameter_factory */
-static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, zend_bool required, zval *object)
+static void reflection_parameter_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, uint32_t offset, bool required, zval *object)
{
reflection_object *intern;
parameter_reference *reference;
@@ -1309,7 +1328,7 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
/* For backwards compatibility reasons, we need to return T|null style unions
* as a ReflectionNamedType. Here we determine what counts as a union type and
* what doesn't. */
-static zend_bool is_union_type(zend_type type) {
+static bool is_union_type(zend_type type) {
if (ZEND_TYPE_HAS_LIST(type)) {
return 1;
}
@@ -1325,12 +1344,12 @@ static zend_bool is_union_type(zend_type type) {
}
/* {{{ reflection_type_factory */
-static void reflection_type_factory(zend_type type, zval *object, zend_bool legacy_behavior)
+static void reflection_type_factory(zend_type type, zval *object, bool legacy_behavior)
{
reflection_object *intern;
type_reference *reference;
- zend_bool is_union = is_union_type(type);
- zend_bool is_mixed = ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY;
+ bool is_union = is_union_type(type);
+ bool is_mixed = ZEND_TYPE_PURE_MASK(type) == MAY_BE_ANY;
reflection_instantiate(is_union && !is_mixed ? reflection_union_type_ptr : reflection_named_type_ptr, object);
intern = Z_REFLECTION_P(object);
@@ -1430,6 +1449,24 @@ static void reflection_class_constant_factory(zend_string *name_str, zend_class_
}
/* }}} */
+static void reflection_enum_case_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
+{
+ reflection_object *intern;
+
+ zend_class_entry *case_reflection_class = ce->backed_enum_table == IS_UNDEF
+ ? reflection_enum_unit_case_ptr
+ : reflection_enum_backed_case_ptr;
+ reflection_instantiate(case_reflection_class, object);
+ intern = Z_REFLECTION_P(object);
+ intern->ptr = constant;
+ intern->ref_type = REF_TYPE_CLASS_CONSTANT;
+ intern->ce = constant->ce;
+ intern->ignore_visibility = 0;
+
+ ZVAL_STR_COPY(reflection_prop_name(object), name_str);
+ ZVAL_STR_COPY(reflection_prop_class(object), constant->ce->name);
+}
+
static int get_parameter_default(zval *result, parameter_reference *param) {
if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
if (param->fptr->common.fn_flags & ZEND_ACC_USER_ARG_INFO) {
@@ -1801,7 +1838,6 @@ ZEND_METHOD(ReflectionFunctionAbstract, getStaticVariables)
array_init(return_value);
ht = ZEND_MAP_PTR_GET(fptr->op_array.static_variables_ptr);
if (!ht) {
- ZEND_ASSERT(fptr->op_array.fn_flags & ZEND_ACC_IMMUTABLE);
ht = zend_array_dup(fptr->op_array.static_variables);
ZEND_MAP_PTR_SET(fptr->op_array.static_variables_ptr, ht);
}
@@ -2249,7 +2285,7 @@ ZEND_METHOD(ReflectionParameter, __construct)
struct _zend_arg_info *arg_info;
uint32_t num_args;
zend_class_entry *ce = NULL;
- zend_bool is_closure = 0;
+ bool is_closure = 0;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(reference)
@@ -2957,8 +2993,14 @@ ZEND_METHOD(ReflectionUnionType, getTypes)
append_type(return_value, *list_type);
} ZEND_TYPE_LIST_FOREACH_END();
} else if (ZEND_TYPE_HAS_NAME(param->type)) {
- append_type(return_value,
- (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_NAME(param->type), 0, 0));
+ if (ZEND_TYPE_HAS_CE_CACHE(param->type)
+ && ZEND_TYPE_CE_CACHE(param->type)) {
+ append_type(return_value,
+ (zend_type) ZEND_TYPE_INIT_CE(ZEND_TYPE_CE_CACHE(param->type), 0, 0));
+ } else {
+ append_type(return_value,
+ (zend_type) ZEND_TYPE_INIT_CLASS(ZEND_TYPE_NAME(param->type), 0, 0));
+ }
} else if (ZEND_TYPE_HAS_CE(param->type)) {
append_type(return_value,
(zend_type) ZEND_TYPE_INIT_CE(ZEND_TYPE_CE(param->type), 0, 0));
@@ -3517,7 +3559,7 @@ ZEND_METHOD(ReflectionMethod, getPrototype)
ZEND_METHOD(ReflectionMethod, setAccessible)
{
reflection_object *intern;
- zend_bool visible;
+ bool visible;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
RETURN_THROWS();
@@ -3557,7 +3599,7 @@ ZEND_METHOD(ReflectionClassConstant, __construct)
object = ZEND_THIS;
intern = Z_REFLECTION_P(object);
- if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
+ if ((constant = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), constname)) == NULL) {
zend_throw_exception_ex(reflection_exception_ptr, 0, "Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
RETURN_THROWS();
}
@@ -3660,10 +3702,10 @@ ZEND_METHOD(ReflectionClassConstant, getValue)
}
GET_REFLECTION_OBJECT_PTR(ref);
- ZVAL_COPY_OR_DUP(return_value, &ref->value);
- if (Z_TYPE_P(return_value) == IS_CONSTANT_AST) {
- zval_update_constant_ex(return_value, ref->ce);
+ if (Z_TYPE(ref->value) == IS_CONSTANT_AST) {
+ zval_update_constant_ex(&ref->value, ref->ce);
}
+ ZVAL_COPY_OR_DUP(return_value, &ref->value);
}
/* }}} */
@@ -3713,6 +3755,16 @@ ZEND_METHOD(ReflectionClassConstant, getAttributes)
}
/* }}} */
+ZEND_METHOD(ReflectionClassConstant, isEnumCase)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & ZEND_CLASS_CONST_IS_CASE);
+}
+
/* {{{ reflection_class_object_ctor */
static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
{
@@ -3764,7 +3816,7 @@ ZEND_METHOD(ReflectionClass, __construct)
/* }}} */
/* {{{ add_class_vars */
-static void add_class_vars(zend_class_entry *ce, zend_bool statics, zval *return_value)
+static void add_class_vars(zend_class_entry *ce, bool statics, zval *return_value)
{
zend_property_info *prop_info;
zval *prop, prop_copy;
@@ -3776,7 +3828,7 @@ static void add_class_vars(zend_class_entry *ce, zend_bool statics, zval *return
continue;
}
- zend_bool is_static = (prop_info->flags & ZEND_ACC_STATIC) != 0;
+ bool is_static = (prop_info->flags & ZEND_ACC_STATIC) != 0;
if (statics != is_static) {
continue;
}
@@ -4208,7 +4260,7 @@ ZEND_METHOD(ReflectionClass, getMethods)
zend_class_entry *ce;
zend_function *mptr;
zend_long filter;
- zend_bool filter_is_null = 1;
+ bool filter_is_null = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
RETURN_THROWS();
@@ -4226,7 +4278,7 @@ ZEND_METHOD(ReflectionClass, getMethods)
} ZEND_HASH_FOREACH_END();
if (instanceof_function(ce, zend_ce_closure)) {
- zend_bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
+ bool has_obj = Z_TYPE(intern->obj) != IS_UNDEF;
zval obj_tmp;
zend_object *obj;
if (!has_obj) {
@@ -4384,7 +4436,7 @@ ZEND_METHOD(ReflectionClass, getProperties)
zend_string *key;
zend_property_info *prop_info;
zend_long filter;
- zend_bool filter_is_null = 1;
+ bool filter_is_null = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
RETURN_THROWS();
@@ -4440,7 +4492,7 @@ ZEND_METHOD(ReflectionClass, getConstants)
zend_class_constant *constant;
zval val;
zend_long filter;
- zend_bool filter_is_null = 1;
+ bool filter_is_null = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
RETURN_THROWS();
@@ -4453,7 +4505,7 @@ ZEND_METHOD(ReflectionClass, getConstants)
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
- ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, constant) {
+ ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), key, constant) {
if (UNEXPECTED(zval_update_constant_ex(&constant->value, ce) != SUCCESS)) {
RETURN_THROWS();
}
@@ -4474,7 +4526,7 @@ ZEND_METHOD(ReflectionClass, getReflectionConstants)
zend_string *name;
zend_class_constant *constant;
zend_long filter;
- zend_bool filter_is_null = 1;
+ bool filter_is_null = 1;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l!", &filter, &filter_is_null) == FAILURE) {
RETURN_THROWS();
@@ -4487,7 +4539,7 @@ ZEND_METHOD(ReflectionClass, getReflectionConstants)
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
- ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
+ ZEND_HASH_FOREACH_STR_KEY_PTR(CE_CONSTANTS_TABLE(ce), name, constant) {
if (Z_ACCESS_FLAGS(constant->value) & filter) {
zval class_const;
reflection_class_constant_factory(name, constant, &class_const);
@@ -4502,6 +4554,7 @@ ZEND_METHOD(ReflectionClass, getConstant)
{
reflection_object *intern;
zend_class_entry *ce;
+ HashTable *constants_table;
zend_class_constant *c;
zend_string *name;
@@ -4510,12 +4563,13 @@ ZEND_METHOD(ReflectionClass, getConstant)
}
GET_REFLECTION_OBJECT_PTR(ce);
- ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
+ constants_table = CE_CONSTANTS_TABLE(ce);
+ ZEND_HASH_FOREACH_PTR(constants_table, c) {
if (UNEXPECTED(zval_update_constant_ex(&c->value, ce) != SUCCESS)) {
RETURN_THROWS();
}
} ZEND_HASH_FOREACH_END();
- if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
+ if ((c = zend_hash_find_ptr(constants_table, name)) == NULL) {
RETURN_FALSE;
}
ZVAL_COPY_OR_DUP(return_value, &c->value);
@@ -4535,7 +4589,7 @@ ZEND_METHOD(ReflectionClass, getReflectionConstant)
RETURN_THROWS();
}
- if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
+ if ((constant = zend_hash_find_ptr(CE_CONSTANTS_TABLE(ce), name)) == NULL) {
RETURN_FALSE;
}
reflection_class_constant_factory(name, constant, return_value);
@@ -4630,6 +4684,11 @@ ZEND_METHOD(ReflectionClass, isTrait)
}
/* }}} */
+ZEND_METHOD(ReflectionClass, isEnum)
+{
+ _class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_ENUM);
+}
+
/* {{{ Returns whether this class is final */
ZEND_METHOD(ReflectionClass, isFinal)
{
@@ -4922,9 +4981,30 @@ ZEND_METHOD(ReflectionClass, getTraitAliases)
zend_trait_method_reference *cur_ref = &ce->trait_aliases[i]->trait_method;
if (ce->trait_aliases[i]->alias) {
+ zend_string *class_name = cur_ref->class_name;
+
+ if (!class_name) {
+ uint32_t j = 0;
+ zval *zv;
+ zend_class_entry *trait;
+ zend_string *lcname = zend_string_tolower(cur_ref->method_name);
+
+ for (j = 0; j < ce->num_traits; j++) {
+ zv = zend_hash_find_ex(CG(class_table), ce->trait_names[j].lc_name, 1);
+ if (zv) {
+ trait = Z_CE_P(zv);
+ if (zend_hash_exists(&trait->function_table, lcname)) {
+ class_name = trait->name;
+ break;
+ }
+ }
+ }
+ zend_string_release_ex(lcname, 0);
+ ZEND_ASSERT(class_name != NULL);
+ }
- mname = zend_string_alloc(ZSTR_LEN(cur_ref->class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
- snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(cur_ref->class_name), ZSTR_VAL(cur_ref->method_name));
+ mname = zend_string_alloc(ZSTR_LEN(class_name) + ZSTR_LEN(cur_ref->method_name) + 2, 0);
+ snprintf(ZSTR_VAL(mname), ZSTR_LEN(mname) + 1, "%s::%s", ZSTR_VAL(class_name), ZSTR_VAL(cur_ref->method_name));
add_assoc_str_ex(return_value, ZSTR_VAL(ce->trait_aliases[i]->alias), ZSTR_LEN(ce->trait_aliases[i]->alias), mname);
}
i++;
@@ -5520,7 +5600,7 @@ ZEND_METHOD(ReflectionProperty, getAttributes)
ZEND_METHOD(ReflectionProperty, setAccessible)
{
reflection_object *intern;
- zend_bool visible;
+ bool visible;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &visible) == FAILURE) {
RETURN_THROWS();
@@ -5798,7 +5878,7 @@ ZEND_METHOD(ReflectionExtension, getINIEntries)
/* }}} */
/* {{{ add_extension_class */
-static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, zend_bool add_reflection_class)
+static void add_extension_class(zend_class_entry *ce, zend_string *key, zval *class_array, zend_module_entry *module, bool add_reflection_class)
{
if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module && !strcasecmp(ce->info.internal.module->name, module->name)) {
zend_string *name;
@@ -6117,7 +6197,7 @@ ZEND_METHOD(ReflectionReference, __construct)
}
/* }}} */
-static zend_bool is_ignorable_reference(HashTable *ht, zval *ref) {
+static bool is_ignorable_reference(HashTable *ht, zval *ref) {
if (Z_REFCOUNT_P(ref) != 1) {
return 0;
}
@@ -6466,6 +6546,194 @@ ZEND_METHOD(ReflectionAttribute, newInstance)
RETURN_COPY_VALUE(&obj);
}
+ZEND_METHOD(ReflectionEnum, __construct)
+{
+ reflection_class_object_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ if (EG(exception)) {
+ RETURN_THROWS();
+ }
+
+ reflection_object *intern;
+ zend_class_entry *ce;
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ if (!(ce->ce_flags & ZEND_ACC_ENUM)) {
+ zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" is not an enum", ZSTR_VAL(ce->name));
+ RETURN_THROWS();
+ }
+}
+
+ZEND_METHOD(ReflectionEnum, hasCase)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_string *name;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ zend_class_constant *class_const = zend_hash_find_ptr(&ce->constants_table, name);
+ if (class_const == NULL) {
+ RETURN_FALSE;
+ }
+
+ RETURN_BOOL(Z_ACCESS_FLAGS(class_const->value) & ZEND_CLASS_CONST_IS_CASE);
+}
+
+ZEND_METHOD(ReflectionEnum, getCase)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_string *name;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ zend_class_constant *constant = zend_hash_find_ptr(&ce->constants_table, name);
+ if (constant == NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "Case %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ RETURN_THROWS();
+ }
+ if (!(Z_ACCESS_FLAGS(constant->value) & ZEND_CLASS_CONST_IS_CASE)) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "%s::%s is not a case", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ RETURN_THROWS();
+ }
+
+ reflection_enum_case_factory(ce, name, constant, return_value);
+}
+
+ZEND_METHOD(ReflectionEnum, getCases)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_string *name;
+ zend_class_constant *constant;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ array_init(return_value);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
+ if (Z_ACCESS_FLAGS(constant->value) & ZEND_CLASS_CONST_IS_CASE) {
+ zval class_const;
+ reflection_enum_case_factory(ce, name, constant, &class_const);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
+ }
+ } ZEND_HASH_FOREACH_END();
+}
+
+ZEND_METHOD(ReflectionEnum, isBacked)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+ RETURN_BOOL(ce->enum_backing_type != IS_UNDEF);
+}
+
+ZEND_METHOD(ReflectionEnum, getBackingType)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+
+ if (ce->enum_backing_type == IS_UNDEF) {
+ RETURN_NULL();
+ } else {
+ zend_type type = ZEND_TYPE_INIT_CODE(ce->enum_backing_type, 0, 0);
+ reflection_type_factory(type, return_value, 0);
+ }
+}
+
+ZEND_METHOD(ReflectionEnumUnitCase, __construct)
+{
+ ZEND_MN(ReflectionClassConstant___construct)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (EG(exception)) {
+ RETURN_THROWS();
+ }
+
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ if (!(Z_ACCESS_FLAGS(ref->value) & ZEND_CLASS_CONST_IS_CASE)) {
+ zval *case_name = reflection_prop_name(ZEND_THIS);
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "Constant %s::%s is not a case", ZSTR_VAL(ref->ce->name), Z_STRVAL_P(case_name));
+ RETURN_THROWS();
+ }
+}
+
+ZEND_METHOD(ReflectionEnumUnitCase, getEnum)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ zend_reflection_enum_factory(ref->ce, return_value);
+}
+
+ZEND_METHOD(ReflectionEnumBackedCase, __construct)
+{
+ ZEND_MN(ReflectionEnumUnitCase___construct)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ if (EG(exception)) {
+ RETURN_THROWS();
+ }
+
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ if (ref->ce->enum_backing_type == IS_UNDEF) {
+ zval *case_name = reflection_prop_name(ZEND_THIS);
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "Enum case %s::%s is not a backed case", ZSTR_VAL(ref->ce->name), Z_STRVAL_P(case_name));
+ RETURN_THROWS();
+ }
+}
+
+ZEND_METHOD(ReflectionEnumBackedCase, getBackingValue)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ RETURN_THROWS();
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ if (Z_TYPE(ref->value) == IS_CONSTANT_AST) {
+ zval_update_constant_ex(&ref->value, ref->ce);
+ }
+
+ ZEND_ASSERT(intern->ce->enum_backing_type != IS_UNDEF);
+ zval *member_p = zend_enum_fetch_case_value(Z_OBJ(ref->value));
+
+ ZVAL_COPY_OR_DUP(return_value, member_p);
+}
+
/* {{{ _reflection_write_property */
static zval *_reflection_write_property(zend_object *object, zend_string *name, zval *value, void **cache_slot)
{
@@ -6491,8 +6759,6 @@ static void reflection_init_class_handlers(zend_class_entry *ce) {
PHP_MINIT_FUNCTION(reflection) /* {{{ */
{
- zend_class_entry _reflection_entry;
-
memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo);
reflection_object_handlers.free_obj = reflection_free_objects_storage;
@@ -6500,59 +6766,37 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
reflection_object_handlers.write_property = _reflection_write_property;
reflection_object_handlers.get_gc = reflection_get_gc;
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionException", class_ReflectionException_methods);
- reflection_exception_ptr = zend_register_internal_class_ex(&_reflection_entry, zend_ce_exception);
+ reflection_exception_ptr = register_class_ReflectionException(zend_ce_exception);
- INIT_CLASS_ENTRY(_reflection_entry, "Reflection", class_Reflection_methods);
- reflection_ptr = zend_register_internal_class(&_reflection_entry);
+ reflection_ptr = register_class_Reflection();
- INIT_CLASS_ENTRY(_reflection_entry, "Reflector", class_Reflector_methods);
- reflector_ptr = zend_register_internal_interface(&_reflection_entry);
- zend_class_implements(reflector_ptr, 1, zend_ce_stringable);
+ reflector_ptr = register_class_Reflector(zend_ce_stringable);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunctionAbstract", class_ReflectionFunctionAbstract_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_function_abstract_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_function_abstract_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_function_abstract_ptr, "name", sizeof("name")-1, "", ZEND_ACC_ABSTRACT);
+ reflection_function_abstract_ptr = register_class_ReflectionFunctionAbstract(reflector_ptr);
+ reflection_init_class_handlers(reflection_function_abstract_ptr);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionFunction", class_ReflectionFunction_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_function_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
- zend_declare_property_string(reflection_function_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
+ reflection_function_ptr = register_class_ReflectionFunction(reflection_function_abstract_ptr);
+ reflection_init_class_handlers(reflection_function_ptr);
REGISTER_REFLECTION_CLASS_CONST_LONG(function, "IS_DEPRECATED", ZEND_ACC_DEPRECATED);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionGenerator", class_ReflectionGenerator_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_generator_ptr = zend_register_internal_class(&_reflection_entry);
- reflection_generator_ptr->ce_flags |= ZEND_ACC_FINAL;
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionParameter", class_ReflectionParameter_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_parameter_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", class_ReflectionType_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
- reflection_type_ptr->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
- zend_class_implements(reflection_type_ptr, 1, zend_ce_stringable);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionNamedType", class_ReflectionNamedType_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_named_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionUnionType", class_ReflectionUnionType_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_union_type_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_type_ptr);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", class_ReflectionMethod_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
- zend_declare_property_string(reflection_method_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
- zend_declare_property_string(reflection_method_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
+ reflection_generator_ptr = register_class_ReflectionGenerator();
+ reflection_init_class_handlers(reflection_generator_ptr);
+
+ reflection_parameter_ptr = register_class_ReflectionParameter(reflector_ptr);
+ reflection_init_class_handlers(reflection_parameter_ptr);
+
+ reflection_type_ptr = register_class_ReflectionType(zend_ce_stringable);
+ reflection_init_class_handlers(reflection_type_ptr);
+
+ reflection_named_type_ptr = register_class_ReflectionNamedType(reflection_type_ptr);
+ reflection_init_class_handlers(reflection_named_type_ptr);
+
+ reflection_union_type_ptr = register_class_ReflectionUnionType(reflection_type_ptr);
+ reflection_init_class_handlers(reflection_union_type_ptr);
+
+ reflection_method_ptr = register_class_ReflectionMethod(reflection_function_abstract_ptr);
+ reflection_init_class_handlers(reflection_method_ptr);
REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_STATIC", ZEND_ACC_STATIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_PUBLIC", ZEND_ACC_PUBLIC);
@@ -6561,65 +6805,52 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_ABSTRACT", ZEND_ACC_ABSTRACT);
REGISTER_REFLECTION_CLASS_CONST_LONG(method, "IS_FINAL", ZEND_ACC_FINAL);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClass", class_ReflectionClass_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_class_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_class_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_class_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
+ reflection_class_ptr = register_class_ReflectionClass(reflector_ptr);
+ reflection_init_class_handlers(reflection_class_ptr);
/* IS_IMPLICIT_ABSTRACT is not longer used */
REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_IMPLICIT_ABSTRACT", ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_EXPLICIT_ABSTRACT", ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
REGISTER_REFLECTION_CLASS_CONST_LONG(class, "IS_FINAL", ZEND_ACC_FINAL);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionObject", class_ReflectionObject_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_object_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_class_ptr);
+ reflection_object_ptr = register_class_ReflectionObject(reflection_class_ptr);
+ reflection_init_class_handlers(reflection_object_ptr);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionProperty", class_ReflectionProperty_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_property_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_property_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_property_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
- zend_declare_property_string(reflection_property_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
+ reflection_property_ptr = register_class_ReflectionProperty(reflector_ptr);
+ reflection_init_class_handlers(reflection_property_ptr);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_STATIC", ZEND_ACC_STATIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PUBLIC", ZEND_ACC_PUBLIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PROTECTED", ZEND_ACC_PROTECTED);
REGISTER_REFLECTION_CLASS_CONST_LONG(property, "IS_PRIVATE", ZEND_ACC_PRIVATE);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", class_ReflectionClassConstant_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_class_constant_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_class_constant_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_class_constant_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
- zend_declare_property_string(reflection_class_constant_ptr, "class", sizeof("class")-1, "", ZEND_ACC_PUBLIC);
+ reflection_class_constant_ptr = register_class_ReflectionClassConstant(reflector_ptr);
+ reflection_init_class_handlers(reflection_class_constant_ptr);
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PUBLIC", ZEND_ACC_PUBLIC);
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PROTECTED", ZEND_ACC_PROTECTED);
REGISTER_REFLECTION_CLASS_CONST_LONG(class_constant, "IS_PRIVATE", ZEND_ACC_PRIVATE);
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionExtension", class_ReflectionExtension_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_extension_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_extension_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionZendExtension", class_ReflectionZendExtension_methods);
- reflection_init_class_handlers(&_reflection_entry);
- reflection_zend_extension_ptr = zend_register_internal_class(&_reflection_entry);
- zend_class_implements(reflection_zend_extension_ptr, 1, reflector_ptr);
- zend_declare_property_string(reflection_zend_extension_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionReference", class_ReflectionReference_methods);
- reflection_init_class_handlers(&_reflection_entry);
- _reflection_entry.ce_flags |= ZEND_ACC_FINAL;
- reflection_reference_ptr = zend_register_internal_class(&_reflection_entry);
-
- INIT_CLASS_ENTRY(_reflection_entry, "ReflectionAttribute", class_ReflectionAttribute_methods);
- reflection_init_class_handlers(&_reflection_entry);
- _reflection_entry.ce_flags |= ZEND_ACC_FINAL;
- reflection_attribute_ptr = zend_register_internal_class(&_reflection_entry);
+ reflection_extension_ptr = register_class_ReflectionExtension(reflector_ptr);
+ reflection_init_class_handlers(reflection_extension_ptr);
+
+ reflection_zend_extension_ptr = register_class_ReflectionZendExtension(reflector_ptr);
+ reflection_init_class_handlers(reflection_zend_extension_ptr);
+
+ reflection_reference_ptr = register_class_ReflectionReference();
+ reflection_init_class_handlers(reflection_reference_ptr);
+
+ reflection_attribute_ptr = register_class_ReflectionAttribute();
+ reflection_init_class_handlers(reflection_attribute_ptr);
+
+ reflection_enum_ptr = register_class_ReflectionEnum(reflection_class_ptr);
+ reflection_init_class_handlers(reflection_enum_ptr);
+
+ reflection_enum_unit_case_ptr = register_class_ReflectionEnumUnitCase(reflection_class_constant_ptr);
+ reflection_init_class_handlers(reflection_enum_unit_case_ptr);
+
+ reflection_enum_backed_case_ptr = register_class_ReflectionEnumBackedCase(reflection_enum_unit_case_ptr);
+ reflection_init_class_handlers(reflection_enum_backed_case_ptr);
REGISTER_REFLECTION_CLASS_CONST_LONG(attribute, "IS_INSTANCEOF", REFLECTION_ATTRIBUTE_IS_INSTANCEOF);