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.c348
1 files changed, 334 insertions, 14 deletions
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 80001e4997..51ed11710d 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -64,6 +64,7 @@ PHPAPI zend_class_entry *reflection_class_ptr;
PHPAPI zend_class_entry *reflection_object_ptr;
PHPAPI zend_class_entry *reflection_method_ptr;
PHPAPI zend_class_entry *reflection_property_ptr;
+PHPAPI zend_class_entry *reflection_class_constant_ptr;
PHPAPI zend_class_entry *reflection_extension_ptr;
PHPAPI zend_class_entry *reflection_zend_extension_ptr;
@@ -215,7 +216,8 @@ typedef enum {
REF_TYPE_PARAMETER,
REF_TYPE_TYPE,
REF_TYPE_PROPERTY,
- REF_TYPE_DYNAMIC_PROPERTY
+ REF_TYPE_DYNAMIC_PROPERTY,
+ REF_TYPE_CLASS_CONSTANT
} reflection_type_t;
/* Struct for reflection objects */
@@ -333,7 +335,7 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
efree(intern->ptr);
break;
case REF_TYPE_GENERATOR:
- break;
+ case REF_TYPE_CLASS_CONSTANT:
case REF_TYPE_OTHER:
break;
}
@@ -368,6 +370,7 @@ static zval *reflection_instantiate(zend_class_entry *pce, zval *object) /* {{{
static void _const_string(string *str, char *name, zval *value, char *indent);
static void _function_string(string *str, zend_function *fptr, zend_class_entry *scope, char* indent);
static void _property_string(string *str, zend_property_info *prop, char *prop_name, char* indent);
+static void _class_const_string(string *str, char *name, zend_class_constant *c, char* indent);
static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *indent);
static void _extension_string(string *str, zend_module_entry *module, char *indent);
static void _zend_extension_string(string *str, zend_extension *extension, char *indent);
@@ -450,11 +453,11 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
string_printf(str, "%s - Constants [%d] {\n", indent, count);
if (count > 0) {
zend_string *key;
- zval *value;
+ zend_class_constant *c;
- ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, value) {
- zval_update_constant_ex(value, 1, NULL);
- _const_string(str, ZSTR_VAL(key), value, indent);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ zval_update_constant_ex(&c->value, 1, NULL);
+ _class_const_string(str, ZSTR_VAL(key), c, indent);
} ZEND_HASH_FOREACH_END();
}
string_printf(str, "%s }\n", indent);
@@ -627,6 +630,20 @@ static void _const_string(string *str, char *name, zval *value, char *indent)
}
/* }}} */
+/* {{{ _class_const_string */
+static void _class_const_string(string *str, char *name, zend_class_constant *c, char *indent)
+{
+ char *type = zend_zval_type_name(&c->value);
+ char *visibility = zend_visibility_string(Z_ACCESS_FLAGS(c->value));
+ zend_string *value_str = zval_get_string(&c->value);
+
+ string_printf(str, "%s Constant [ %s %s %s ] { %s }\n",
+ indent, visibility, type, name, ZSTR_VAL(value_str));
+
+ zend_string_release(value_str);
+}
+/* }}} */
+
/* {{{ _get_recv_opcode */
static zend_op* _get_recv_op(zend_op_array *op_array, uint32_t offset)
{
@@ -1356,6 +1373,27 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
/* }}} */
+/* {{{ reflection_class_constant_factory */
+static void reflection_class_constant_factory(zend_class_entry *ce, zend_string *name_str, zend_class_constant *constant, zval *object)
+{
+ reflection_object *intern;
+ zval name;
+ zval classname;
+
+ ZVAL_STR_COPY(&name, name_str);
+ ZVAL_STR_COPY(&classname, ce->name);
+
+ reflection_instantiate(reflection_class_constant_ptr, object);
+ intern = Z_REFLECTION_P(object);
+ intern->ptr = constant;
+ intern->ref_type = REF_TYPE_CLASS_CONSTANT;
+ intern->ce = constant->ce;
+ intern->ignore_visibility = 0;
+ reflection_update_property(object, "name", &name);
+ reflection_update_property(object, "class", &classname);
+}
+/* }}} */
+
/* {{{ _reflection_export */
static void _reflection_export(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry *ce_ptr, int ctor_argc)
{
@@ -3668,6 +3706,197 @@ ZEND_METHOD(reflection_method, setAccessible)
}
/* }}} */
+/* {{{ proto public void ReflectionClassConstant::__construct(mixed class, string name)
+ Constructor. Throws an Exception in case the given class constant does not exist */
+ZEND_METHOD(reflection_class_constant, __construct)
+{
+ zval *classname, *object, name, cname;
+ zend_string *constname;
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_class_constant *constant = NULL;
+
+ if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "zS", &classname, &constname) == FAILURE) {
+ return;
+ }
+
+ object = getThis();
+ intern = Z_REFLECTION_P(object);
+ if (intern == NULL) {
+ return;
+ }
+
+ /* Find the class entry */
+ switch (Z_TYPE_P(classname)) {
+ case IS_STRING:
+ if ((ce = zend_lookup_class(Z_STR_P(classname))) == NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0,
+ "Class %s does not exist", Z_STRVAL_P(classname));
+ return;
+ }
+ break;
+
+ case IS_OBJECT:
+ ce = Z_OBJCE_P(classname);
+ break;
+
+ default:
+ _DO_THROW("The parameter class is expected to be either a string or an object");
+ /* returns out of this function */
+ }
+
+ if ((constant = zend_hash_find_ptr(&ce->constants_table, constname)) == NULL) {
+ zend_throw_exception_ex(reflection_exception_ptr, 0, "Class Constant %s::%s does not exist", ZSTR_VAL(ce->name), ZSTR_VAL(constname));
+ return;
+ }
+
+ ZVAL_STR_COPY(&name, constname);
+ ZVAL_STR_COPY(&cname, ce->name);
+
+ intern->ptr = constant;
+ intern->ref_type = REF_TYPE_CLASS_CONSTANT;
+ intern->ce = constant->ce;
+ intern->ignore_visibility = 0;
+ reflection_update_property(object, "name", &name);
+ reflection_update_property(object, "class", &cname);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::__toString()
+ Returns a string representation */
+ZEND_METHOD(reflection_class_constant, __toString)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+ string str;
+ zval name;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ string_init(&str);
+ _default_get_entry(getThis(), "name", sizeof("name")-1, &name);
+ _class_const_string(&str, Z_STRVAL(name), ref, "");
+ zval_ptr_dtor(&name);
+ RETURN_NEW_STR(str.buf);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::getName()
+ Returns the constant' name */
+ZEND_METHOD(reflection_class_constant, getName)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ _default_get_entry(getThis(), "name", sizeof("name")-1, return_value);
+}
+/* }}} */
+
+static void _class_constant_check_flag(INTERNAL_FUNCTION_PARAMETERS, int mask) /* {{{ */
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ RETURN_BOOL(Z_ACCESS_FLAGS(ref->value) & mask);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isPublic()
+ Returns whether this constant is public */
+ZEND_METHOD(reflection_class_constant, isPublic)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PUBLIC | ZEND_ACC_IMPLICIT_PUBLIC);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isPrivate()
+ Returns whether this constant is private */
+ZEND_METHOD(reflection_class_constant, isPrivate)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PRIVATE);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionClassConstant::isProtected()
+ Returns whether this constant is protected */
+ZEND_METHOD(reflection_class_constant, isProtected)
+{
+ _class_constant_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_PROTECTED);
+}
+/* }}} */
+
+/* {{{ proto public int ReflectionClassConstant::getModifiers()
+ Returns a bitfield of the access modifiers for this constant */
+ZEND_METHOD(reflection_class_constant, getModifiers)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ RETURN_LONG(Z_ACCESS_FLAGS(ref->value));
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionClassConstant::getValue()
+ Returns this constant's value */
+ZEND_METHOD(reflection_class_constant, getValue)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ ZVAL_DUP(return_value, &ref->value);
+}
+/* }}} */
+
+/* {{{ proto public ReflectionClass ReflectionClassConstant::getDeclaringClass()
+ Get the declaring class */
+ZEND_METHOD(reflection_class_constant, getDeclaringClass)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+
+ zend_reflection_class_factory(ref->ce, return_value);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionClassConstant::getDocComment()
+ Returns the doc comment for this constant */
+ZEND_METHOD(reflection_class_constant, getDocComment)
+{
+ reflection_object *intern;
+ zend_class_constant *ref;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ref);
+ if (ref->doc_comment) {
+ RETURN_STR_COPY(ref->doc_comment);
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
/* {{{ proto public static mixed ReflectionClass::export(mixed argument [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_class, export)
@@ -4414,6 +4643,8 @@ ZEND_METHOD(reflection_class, getConstants)
{
reflection_object *intern;
zend_class_entry *ce;
+ zend_string *key;
+ zend_class_constant *c;
zval *val;
if (zend_parse_parameters_none() == FAILURE) {
@@ -4421,12 +4652,36 @@ ZEND_METHOD(reflection_class, getConstants)
}
GET_REFLECTION_OBJECT_PTR(ce);
array_init(return_value);
- ZEND_HASH_FOREACH_VAL(&ce->constants_table, val) {
- if (UNEXPECTED(zval_update_constant_ex(val, 1, ce) != SUCCESS)) {
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
+ if (UNEXPECTED(zval_update_constant_ex(&c->value, 1, ce) != SUCCESS)) {
+ zend_array_destroy(Z_ARRVAL_P(return_value));
return;
}
+ val = zend_hash_add_new(Z_ARRVAL_P(return_value), key, &c->value);
+ Z_TRY_ADDREF_P(val);
+ } ZEND_HASH_FOREACH_END();
+}
+/* }}} */
+
+/* {{{ proto public array ReflectionClass::getReflectionConstants()
+ Returns an associative array containing this class' constants as ReflectionClassConstant objects */
+ZEND_METHOD(reflection_class, getReflectionConstants)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_string *name;
+ zend_class_constant *constant;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(ce);
+ array_init(return_value);
+ ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, name, constant) {
+ zval class_const;
+ reflection_class_constant_factory(ce, name, constant, &class_const);
+ zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &class_const);
} ZEND_HASH_FOREACH_END();
- zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, zval_add_ref_unref);
}
/* }}} */
@@ -4436,7 +4691,7 @@ ZEND_METHOD(reflection_class, getConstant)
{
reflection_object *intern;
zend_class_entry *ce;
- zval *value;
+ zend_class_constant *c;
zend_string *name;
METHOD_NOTSTATIC(reflection_class_ptr);
@@ -4445,15 +4700,36 @@ ZEND_METHOD(reflection_class, getConstant)
}
GET_REFLECTION_OBJECT_PTR(ce);
- ZEND_HASH_FOREACH_VAL(&ce->constants_table, value) {
- if (UNEXPECTED(zval_update_constant_ex(value, 1, ce) != SUCCESS)) {
+ ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
+ if (UNEXPECTED(zval_update_constant_ex(&c->value, 1, ce) != SUCCESS)) {
return;
}
} ZEND_HASH_FOREACH_END();
- if ((value = zend_hash_find(&ce->constants_table, name)) == NULL) {
+ if ((c = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
RETURN_FALSE;
}
- ZVAL_DUP(return_value, value);
+ ZVAL_DUP(return_value, &c->value);
+}
+/* }}} */
+
+/* {{{ proto public mixed ReflectionClass::getReflectionConstant(string name)
+ Returns the class' constant as ReflectionClassConstant objects */
+ZEND_METHOD(reflection_class, getReflectionConstant)
+{
+ reflection_object *intern;
+ zend_class_entry *ce;
+ zend_class_constant *constant;
+ zend_string *name;
+
+ GET_REFLECTION_OBJECT_PTR(ce);
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &name) == FAILURE) {
+ return;
+ }
+
+ if ((constant = zend_hash_find_ptr(&ce->constants_table, name)) == NULL) {
+ RETURN_FALSE;
+ }
+ reflection_class_constant_factory(ce, name, constant, return_value);
}
/* }}} */
@@ -5171,6 +5447,14 @@ ZEND_METHOD(reflection_property, export)
}
/* }}} */
+/* {{{ proto public static mixed ReflectionClassConstant::export(mixed class, string name [, bool return]) throws ReflectionException
+ Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
+ZEND_METHOD(reflection_class_constant, export)
+{
+ _reflection_export(INTERNAL_FUNCTION_PARAM_PASSTHRU, reflection_class_constant_ptr, 2);
+}
+/* }}} */
+
/* {{{ proto public void ReflectionProperty::__construct(mixed class, string name)
Constructor. Throws an Exception in case the given property does not exist */
ZEND_METHOD(reflection_property, __construct)
@@ -6334,7 +6618,9 @@ static const zend_function_entry reflection_class_functions[] = {
ZEND_ME(reflection_class, getProperties, arginfo_reflection_class_getProperties, 0)
ZEND_ME(reflection_class, hasConstant, arginfo_reflection_class_hasConstant, 0)
ZEND_ME(reflection_class, getConstants, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class, getReflectionConstants, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getConstant, arginfo_reflection_class_getConstant, 0)
+ ZEND_ME(reflection_class, getReflectionConstant, arginfo_reflection_class_getConstant, 0)
ZEND_ME(reflection_class, getInterfaces, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, getInterfaceNames, arginfo_reflection__void, 0)
ZEND_ME(reflection_class, isInterface, arginfo_reflection__void, 0)
@@ -6426,6 +6712,33 @@ static const zend_function_entry reflection_property_functions[] = {
PHP_FE_END
};
+ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant_export, 0, 0, 2)
+ ZEND_ARG_INFO(0, class)
+ ZEND_ARG_INFO(0, name)
+ ZEND_ARG_INFO(0, return)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_class_constant___construct, 0, 0, 2)
+ ZEND_ARG_INFO(0, class)
+ ZEND_ARG_INFO(0, name)
+ZEND_END_ARG_INFO()
+
+static const zend_function_entry reflection_class_constant_functions[] = {
+ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
+ ZEND_ME(reflection_class_constant, export, arginfo_reflection_class_constant_export, ZEND_ACC_STATIC|ZEND_ACC_PUBLIC)
+ ZEND_ME(reflection_class_constant, __construct, arginfo_reflection_class_constant___construct, 0)
+ ZEND_ME(reflection_class_constant, __toString, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getName, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getValue, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isPublic, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isPrivate, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, isProtected, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getModifiers, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getDeclaringClass, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_class_constant, getDocComment, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_parameter_export, 0, 0, 2)
ZEND_ARG_INFO(0, function)
ZEND_ARG_INFO(0, parameter)
@@ -6622,6 +6935,13 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
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);
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionClassConstant", reflection_class_constant_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ 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);
+
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);