diff options
Diffstat (limited to 'ext/reflection/php_reflection.c')
-rw-r--r-- | ext/reflection/php_reflection.c | 485 |
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); |