mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Implemented the RFC Support Class Constant Visibility
.
Squashed commit of the following: commitf11ca0e7a5
Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Dec 8 12:38:42 2015 +0300 Fixed test expectation commit211f873f54
Author: Dmitry Stogov <dmitry@zend.com> Date: Tue Dec 8 12:28:38 2015 +0300 Embed zend_class_constant.flags into zend_class_constants.value.u2.access_flags commit51deab84b2
Author: Dmitry Stogov <dmitry@zend.com> Date: Mon Dec 7 11:18:55 2015 +0300 Fixed issues found by Nikita commit544dbd5b47
Author: Dmitry Stogov <dmitry@zend.com> Date: Sat Dec 5 02:41:05 2015 +0300 Refactored immplementation of https://wiki.php.net/rfc/class_const_visibility @reeze created an RFC here and I emailed internals here and didn't get any responses positive/negative.
This commit is contained in:
parent
a8b7d0c29d
commit
a75c195000
@ -1129,12 +1129,13 @@ ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
|
||||
zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
|
||||
zend_class_entry *old_scope = *scope;
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
zval *val;
|
||||
zend_property_info *prop_info;
|
||||
|
||||
*scope = class_type;
|
||||
ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
|
||||
ZVAL_DEREF(val);
|
||||
ZEND_HASH_FOREACH_PTR(&class_type->constants_table, c) {
|
||||
val = &c->value;
|
||||
if (Z_CONSTANT_P(val)) {
|
||||
if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
|
||||
return FAILURE;
|
||||
@ -3737,16 +3738,49 @@ ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *nam
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
|
||||
ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment) /* {{{ */
|
||||
{
|
||||
zend_class_constant *c;
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
if (access_type != ZEND_ACC_PUBLIC) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface constant %s::%s must be public", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
}
|
||||
|
||||
if (zend_string_equals_literal_ci(name, "class")) {
|
||||
zend_error((ce->type == ZEND_INTERNAL_CLASS) ? E_CORE_ERROR : E_COMPILE_ERROR,
|
||||
"A class constant must not be called 'class'; it is reserved for class name fetching");
|
||||
}
|
||||
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
c = pemalloc(sizeof(zend_class_constant), 1);
|
||||
} else {
|
||||
c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
|
||||
}
|
||||
ZVAL_COPY_VALUE(&c->value, value);
|
||||
Z_ACCESS_FLAGS(c->value) = access_type;
|
||||
c->doc_comment = doc_comment;
|
||||
c->ce = ce;
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
return zend_hash_str_update(&ce->constants_table, name, name_length, value) ?
|
||||
return zend_hash_add_ptr(&ce->constants_table, name, c) ?
|
||||
SUCCESS : FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value) /* {{{ */
|
||||
{
|
||||
int ret;
|
||||
|
||||
zend_string *key = zend_string_init(name, name_length, ce->type & ZEND_INTERNAL_CLASS);
|
||||
ret = zend_declare_class_constant_ex(ce, key, value, ZEND_ACC_PUBLIC, NULL);
|
||||
zend_string_release(key);
|
||||
return ret;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length) /* {{{ */
|
||||
{
|
||||
zval constant;
|
||||
|
@ -324,6 +324,7 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, const char *name
|
||||
ZEND_API int zend_declare_property_string(zend_class_entry *ce, const char *name, size_t name_length, const char *value, int access_type);
|
||||
ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, const char *name, size_t name_length, const char *value, size_t value_len, int access_type);
|
||||
|
||||
ZEND_API int zend_declare_class_constant_ex(zend_class_entry *ce, zend_string *name, zval *value, int access_type, zend_string *doc_comment);
|
||||
ZEND_API int zend_declare_class_constant(zend_class_entry *ce, const char *name, size_t name_length, zval *value);
|
||||
ZEND_API int zend_declare_class_constant_null(zend_class_entry *ce, const char *name, size_t name_length);
|
||||
ZEND_API int zend_declare_class_constant_long(zend_class_entry *ce, const char *name, size_t name_length, zend_long value);
|
||||
|
@ -124,7 +124,6 @@ enum _zend_ast_kind {
|
||||
ZEND_AST_SWITCH,
|
||||
ZEND_AST_SWITCH_CASE,
|
||||
ZEND_AST_DECLARE,
|
||||
ZEND_AST_CONST_ELEM,
|
||||
ZEND_AST_USE_TRAIT,
|
||||
ZEND_AST_TRAIT_PRECEDENCE,
|
||||
ZEND_AST_METHOD_REFERENCE,
|
||||
@ -142,6 +141,7 @@ enum _zend_ast_kind {
|
||||
ZEND_AST_CATCH,
|
||||
ZEND_AST_PARAM,
|
||||
ZEND_AST_PROP_ELEM,
|
||||
ZEND_AST_CONST_ELEM,
|
||||
|
||||
/* 4 child nodes */
|
||||
ZEND_AST_FOR = 4 << ZEND_AST_NUM_CHILDREN_SHIFT,
|
||||
|
@ -97,6 +97,12 @@ static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void zend_destroy_class_constant_internal(zval *zv) /* {{{ */
|
||||
{
|
||||
free(Z_PTR_P(zv));
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_string *zend_new_interned_string_safe(zend_string *str) /* {{{ */ {
|
||||
zend_string *interned_str;
|
||||
|
||||
@ -1437,14 +1443,15 @@ static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_a
|
||||
static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
|
||||
{
|
||||
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
|
||||
zend_class_constant *cc;
|
||||
zval *c;
|
||||
|
||||
if (class_name_refers_to_active_ce(class_name, fetch_type)) {
|
||||
c = zend_hash_find(&CG(active_class_entry)->constants_table, name);
|
||||
cc = zend_hash_find_ptr(&CG(active_class_entry)->constants_table, name);
|
||||
} else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
|
||||
zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), ZSTR_VAL(class_name), ZSTR_LEN(class_name));
|
||||
if (ce) {
|
||||
c = zend_hash_find(&ce->constants_table, name);
|
||||
cc = zend_hash_find_ptr(&ce->constants_table, name);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@ -1456,8 +1463,14 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cc || !zend_verify_const_access(cc, CG(active_class_entry))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = &cc->value;
|
||||
|
||||
/* Substitute case-sensitive (or lowercase) persistent class constants */
|
||||
if (c && Z_TYPE_P(c) < IS_OBJECT) {
|
||||
if (Z_TYPE_P(c) < IS_OBJECT) {
|
||||
ZVAL_DUP(zv, c);
|
||||
return 1;
|
||||
}
|
||||
@ -1638,7 +1651,6 @@ again:
|
||||
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) /* {{{ */
|
||||
{
|
||||
zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0;
|
||||
dtor_func_t zval_ptr_dtor_func = ((persistent_hashes) ? ZVAL_INTERNAL_PTR_DTOR : ZVAL_PTR_DTOR);
|
||||
|
||||
ce->refcount = 1;
|
||||
ce->ce_flags = ZEND_ACC_CONSTANTS_UPDATED;
|
||||
@ -1650,7 +1662,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
|
||||
ce->default_properties_table = NULL;
|
||||
ce->default_static_members_table = NULL;
|
||||
zend_hash_init_ex(&ce->properties_info, 8, NULL, (persistent_hashes ? zend_destroy_property_info_internal : NULL), persistent_hashes, 0);
|
||||
zend_hash_init_ex(&ce->constants_table, 8, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
|
||||
zend_hash_init_ex(&ce->constants_table, 8, NULL, (persistent_hashes ? zend_destroy_class_constant_internal : NULL), persistent_hashes, 0);
|
||||
zend_hash_init_ex(&ce->function_table, 8, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
|
||||
|
||||
if (ce->type == ZEND_INTERNAL_CLASS) {
|
||||
@ -5183,25 +5195,28 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
|
||||
zend_ast *const_ast = list->child[i];
|
||||
zend_ast *name_ast = const_ast->child[0];
|
||||
zend_ast *value_ast = const_ast->child[1];
|
||||
zend_ast *doc_comment_ast = const_ast->child[2];
|
||||
zend_string *name = zend_ast_get_str(name_ast);
|
||||
zend_string *doc_comment = doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL;
|
||||
zval value_zv;
|
||||
|
||||
if (zend_string_equals_literal_ci(name, "class")) {
|
||||
zend_error(E_COMPILE_ERROR,
|
||||
"A class constant must not be called 'class'; it is reserved for class name fetching");
|
||||
if (UNEXPECTED(ast->attr & (ZEND_ACC_STATIC|ZEND_ACC_ABSTRACT|ZEND_ACC_FINAL))) {
|
||||
if (ast->attr & ZEND_ACC_STATIC) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'static' as constant modifier");
|
||||
} else if (ast->attr & ZEND_ACC_ABSTRACT) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'abstract' as constant modifier");
|
||||
} else if (ast->attr & ZEND_ACC_FINAL) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use 'final' as constant modifier");
|
||||
}
|
||||
}
|
||||
|
||||
zend_const_expr_to_zval(&value_zv, value_ast);
|
||||
|
||||
name = zend_new_interned_string_safe(name);
|
||||
if (zend_hash_add(&ce->constants_table, name, &value_zv) == NULL) {
|
||||
if (zend_declare_class_constant_ex(ce, name, &value_zv, ast->attr, doc_comment) != SUCCESS) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||
}
|
||||
|
||||
if (Z_CONSTANT(value_zv)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -310,6 +310,12 @@ typedef struct _zend_property_info {
|
||||
#define OBJ_PROP_TO_NUM(offset) \
|
||||
((offset - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval))
|
||||
|
||||
typedef struct _zend_class_constant {
|
||||
zval value; /* access flags are stored in reserved: zval.u2.access_flags */
|
||||
zend_string *doc_comment;
|
||||
zend_class_entry *ce;
|
||||
} zend_class_constant;
|
||||
|
||||
/* arg_info for internal functions */
|
||||
typedef struct _zend_internal_arg_info {
|
||||
const char *name;
|
||||
|
@ -251,6 +251,18 @@ static zend_constant *zend_get_special_constant(const char *name, size_t name_le
|
||||
}
|
||||
}
|
||||
|
||||
ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *scope) /* {{{ */
|
||||
{
|
||||
if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PUBLIC) {
|
||||
return 1;
|
||||
} else if (Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PRIVATE) {
|
||||
return (c->ce == scope);
|
||||
} else {
|
||||
ZEND_ASSERT(Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PROTECTED);
|
||||
return zend_check_protected(c->ce, scope);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len)
|
||||
{
|
||||
@ -360,16 +372,23 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
|
||||
}
|
||||
free_alloca(lcname, use_heap);
|
||||
if (ce) {
|
||||
ret_constant = zend_hash_find(&ce->constants_table, constant_name);
|
||||
if (ret_constant == NULL) {
|
||||
zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, constant_name);
|
||||
if (c == NULL) {
|
||||
if ((flags & ZEND_FETCH_CLASS_SILENT) == 0) {
|
||||
zend_throw_error(NULL, "Undefined class constant '%s::%s'", ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
|
||||
zend_string_release(class_name);
|
||||
zend_string_free(constant_name);
|
||||
return NULL;
|
||||
}
|
||||
} else if (Z_ISREF_P(ret_constant)) {
|
||||
ret_constant = Z_REFVAL_P(ret_constant);
|
||||
ret_constant = NULL;
|
||||
} else {
|
||||
if (!zend_verify_const_access(c, scope)) {
|
||||
zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(class_name), ZSTR_VAL(constant_name));
|
||||
zend_string_release(class_name);
|
||||
zend_string_free(constant_name);
|
||||
return NULL;
|
||||
}
|
||||
ret_constant = &c->value;
|
||||
}
|
||||
}
|
||||
zend_string_release(class_name);
|
||||
|
@ -65,6 +65,7 @@ int zend_startup_constants(void);
|
||||
int zend_shutdown_constants(void);
|
||||
void zend_register_standard_constants(void);
|
||||
void clean_non_persistent_constants(void);
|
||||
ZEND_API int zend_verify_const_access(zend_class_constant *c, zend_class_entry *ce);
|
||||
ZEND_API zval *zend_get_constant(zend_string *name);
|
||||
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len);
|
||||
ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, uint32_t flags);
|
||||
|
@ -698,21 +698,29 @@ ZEND_API void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void do_inherit_class_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *parent_ce) /* {{{ */
|
||||
static void do_inherit_class_constant(zend_string *name, zend_class_constant *parent_const, zend_class_entry *ce) /* {{{ */
|
||||
{
|
||||
if (!zend_hash_exists(&ce->constants_table, name)) {
|
||||
if (!Z_ISREF_P(zv)) {
|
||||
if (parent_ce->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_NEW_PERSISTENT_REF(zv, zv);
|
||||
} else {
|
||||
ZVAL_NEW_REF(zv, zv);
|
||||
zend_class_constant *c = zend_hash_find_ptr(&ce->constants_table, name);
|
||||
|
||||
if (c != NULL) {
|
||||
if (UNEXPECTED((Z_ACCESS_FLAGS(c->value) & ZEND_ACC_PPP_MASK) > (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PPP_MASK))) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Access level to %s::%s must be %s (as in class %s)%s",
|
||||
ZSTR_VAL(ce->name), ZSTR_VAL(name), zend_visibility_string(Z_ACCESS_FLAGS(parent_const->value)), ZSTR_VAL(ce->parent->name), (Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PUBLIC) ? "" : " or weaker");
|
||||
}
|
||||
}
|
||||
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
|
||||
} else if (!(Z_ACCESS_FLAGS(parent_const->value) & ZEND_ACC_PRIVATE)) {
|
||||
if (Z_CONSTANT(parent_const->value)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
Z_ADDREF_P(zv);
|
||||
_zend_hash_append(&ce->constants_table, name, zv);
|
||||
if (Z_REFCOUNTED(parent_const->value)) {
|
||||
Z_ADDREF(parent_const->value);
|
||||
}
|
||||
if (ce->type & ZEND_INTERNAL_CLASS) {
|
||||
c = pemalloc(sizeof(zend_class_constant), 1);
|
||||
} else {
|
||||
c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant));
|
||||
}
|
||||
memcpy(c, parent_const, sizeof(zend_class_constant));
|
||||
_zend_hash_append_ptr(&ce->constants_table, name, c);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@ -722,7 +730,6 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
zend_property_info *property_info;
|
||||
zend_function *func;
|
||||
zend_string *key;
|
||||
zval *zv;
|
||||
|
||||
if (UNEXPECTED(ce->ce_flags & ZEND_ACC_INTERFACE)) {
|
||||
/* Interface can only inherit other interfaces */
|
||||
@ -859,12 +866,14 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
}
|
||||
|
||||
if (zend_hash_num_elements(&parent_ce->constants_table)) {
|
||||
zend_class_constant *c;
|
||||
|
||||
zend_hash_extend(&ce->constants_table,
|
||||
zend_hash_num_elements(&ce->constants_table) +
|
||||
zend_hash_num_elements(&parent_ce->constants_table), 0);
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&parent_ce->constants_table, key, zv) {
|
||||
do_inherit_class_constant(key, zv, ce, parent_ce);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&parent_ce->constants_table, key, c) {
|
||||
do_inherit_class_constant(key, c, ce);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
}
|
||||
|
||||
@ -894,14 +903,12 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
|
||||
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zend_class_constant *parent_constant, zend_string *name, const zend_class_entry *iface) /* {{{ */
|
||||
{
|
||||
zval *old_constant;
|
||||
zend_class_constant *old_constant;
|
||||
|
||||
if ((old_constant = zend_hash_find(child_constants_table, name)) != NULL) {
|
||||
if (!Z_ISREF_P(old_constant) ||
|
||||
!Z_ISREF_P(parent_constant) ||
|
||||
Z_REFVAL_P(old_constant) != Z_REFVAL_P(parent_constant)) {
|
||||
if ((old_constant = zend_hash_find_ptr(child_constants_table, name)) != NULL) {
|
||||
if (old_constant->ce != parent_constant->ce) {
|
||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot inherit previously-inherited or override constant %s from interface %s", ZSTR_VAL(name), ZSTR_VAL(iface->name));
|
||||
}
|
||||
return 0;
|
||||
@ -910,21 +917,16 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zva
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void do_inherit_iface_constant(zend_string *name, zval *zv, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
|
||||
static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */
|
||||
{
|
||||
if (do_inherit_constant_check(&ce->constants_table, zv, name, iface)) {
|
||||
if (!Z_ISREF_P(zv)) {
|
||||
if (iface->type == ZEND_INTERNAL_CLASS) {
|
||||
ZVAL_NEW_PERSISTENT_REF(zv, zv);
|
||||
} else {
|
||||
ZVAL_NEW_REF(zv, zv);
|
||||
if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) {
|
||||
if (Z_REFCOUNTED(c->value)) {
|
||||
Z_ADDREF(c->value);
|
||||
}
|
||||
}
|
||||
Z_ADDREF_P(zv);
|
||||
if (Z_CONSTANT_P(Z_REFVAL_P(zv))) {
|
||||
if (Z_CONSTANT(c->value)) {
|
||||
ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
|
||||
}
|
||||
zend_hash_update(&ce->constants_table, name, zv);
|
||||
zend_hash_update_ptr(&ce->constants_table, name, c);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@ -936,7 +938,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
uint32_t parent_iface_num = ce->parent ? ce->parent->num_interfaces : 0;
|
||||
zend_function *func;
|
||||
zend_string *key;
|
||||
zval *zv;
|
||||
zend_class_constant *c;
|
||||
|
||||
for (i = 0; i < ce->num_interfaces; i++) {
|
||||
if (ce->interfaces[i] == NULL) {
|
||||
@ -952,8 +954,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
if (ignore) {
|
||||
/* Check for attempt to redeclare interface constants */
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&ce->constants_table, key, zv) {
|
||||
do_inherit_constant_check(&iface->constants_table, zv, key, iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->constants_table, key, c) {
|
||||
do_inherit_constant_check(&iface->constants_table, c, key, iface);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else {
|
||||
if (ce->num_interfaces >= current_iface_num) {
|
||||
@ -965,8 +967,8 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry
|
||||
}
|
||||
ce->interfaces[ce->num_interfaces++] = iface;
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_VAL(&iface->constants_table, key, zv) {
|
||||
do_inherit_iface_constant(key, zv, ce, iface);
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->constants_table, key, c) {
|
||||
do_inherit_iface_constant(key, c, ce, iface);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
ZEND_HASH_FOREACH_STR_KEY_PTR(&iface->function_table, key, func) {
|
||||
|
@ -701,8 +701,8 @@ class_statement_list:
|
||||
class_statement:
|
||||
variable_modifiers property_list ';'
|
||||
{ $$ = $2; $$->attr = $1; }
|
||||
| T_CONST class_const_list ';'
|
||||
{ $$ = $2; RESET_DOC_COMMENT(); }
|
||||
| method_modifiers T_CONST class_const_list ';'
|
||||
{ $$ = $3; $$->attr = $1; }
|
||||
| T_USE name_list trait_adaptations
|
||||
{ $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); }
|
||||
| method_modifiers function returns_ref identifier '(' parameter_list ')'
|
||||
@ -810,11 +810,11 @@ class_const_list:
|
||||
;
|
||||
|
||||
class_const_decl:
|
||||
identifier '=' expr { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3); }
|
||||
identifier '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
|
||||
;
|
||||
|
||||
const_decl:
|
||||
T_STRING '=' expr { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3); }
|
||||
T_STRING '=' expr backup_doc_comment { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3, ($4 ? zend_ast_create_zval_from_str($4) : NULL)); }
|
||||
;
|
||||
|
||||
echo_expr_list:
|
||||
|
@ -287,7 +287,17 @@ ZEND_API void destroy_zend_class(zval *zv)
|
||||
zend_hash_destroy(&ce->properties_info);
|
||||
zend_string_release(ce->name);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
if (zend_hash_num_elements(&ce->constants_table)) {
|
||||
zend_class_constant *c;
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
|
||||
zval_ptr_dtor(&c->value);
|
||||
if (c->doc_comment && c->ce == ce) {
|
||||
zend_string_release(c->doc_comment);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
zend_hash_destroy(&ce->constants_table);
|
||||
}
|
||||
if (ce->num_interfaces > 0 && ce->interfaces) {
|
||||
efree(ce->interfaces);
|
||||
}
|
||||
@ -322,7 +332,17 @@ ZEND_API void destroy_zend_class(zval *zv)
|
||||
zend_hash_destroy(&ce->properties_info);
|
||||
zend_string_release(ce->name);
|
||||
zend_hash_destroy(&ce->function_table);
|
||||
if (zend_hash_num_elements(&ce->constants_table)) {
|
||||
zend_class_constant *c;
|
||||
|
||||
ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) {
|
||||
zval_internal_ptr_dtor(&c->value);
|
||||
if (c->doc_comment && c->ce == ce) {
|
||||
zend_string_release(c->doc_comment);
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
zend_hash_destroy(&ce->constants_table);
|
||||
}
|
||||
if (ce->num_interfaces > 0) {
|
||||
free(ce->interfaces);
|
||||
}
|
||||
|
@ -138,6 +138,7 @@ struct _zval_struct {
|
||||
uint32_t num_args; /* arguments number for EX(This) */
|
||||
uint32_t fe_pos; /* foreach position */
|
||||
uint32_t fe_iter_idx; /* foreach iterator index */
|
||||
uint32_t access_flags; /* class constant access flags */
|
||||
} u2;
|
||||
};
|
||||
|
||||
@ -361,6 +362,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
|
||||
#define Z_FE_ITER(zval) (zval).u2.fe_iter_idx
|
||||
#define Z_FE_ITER_P(zval_p) Z_FE_ITER(*(zval_p))
|
||||
|
||||
#define Z_ACCESS_FLAGS(zval) (zval).u2.access_flags
|
||||
#define Z_ACCESS_FLAGS_P(zval_p) Z_ACCESS_FLAGS(*(zval_p))
|
||||
|
||||
#define Z_COUNTED(zval) (zval).value.counted
|
||||
#define Z_COUNTED_P(zval_p) Z_COUNTED(*(zval_p))
|
||||
|
||||
|
@ -5163,6 +5163,7 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST, CONST_FETCH)
|
||||
ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
zval *value;
|
||||
USE_OPLINE
|
||||
|
||||
@ -5172,7 +5173,6 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
if (OP1_TYPE == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
@ -5200,13 +5200,16 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
ZVAL_DEREF(value);
|
||||
if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
if (!zend_verify_const_access(c, EG(scope))) {
|
||||
zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
value = &c->value;
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
|
@ -5824,6 +5824,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
zval *value;
|
||||
USE_OPLINE
|
||||
|
||||
@ -5833,7 +5834,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS
|
||||
if (IS_CONST == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
@ -5861,13 +5861,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONS
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
ZVAL_DEREF(value);
|
||||
if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
if (!zend_verify_const_access(c, EG(scope))) {
|
||||
zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
value = &c->value;
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
@ -17546,6 +17549,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
zval *value;
|
||||
USE_OPLINE
|
||||
|
||||
@ -17555,7 +17559,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_
|
||||
if (IS_VAR == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
@ -17583,13 +17586,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
ZVAL_DEREF(value);
|
||||
if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
if (!zend_verify_const_access(c, EG(scope))) {
|
||||
zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
value = &c->value;
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
@ -23883,8 +23889,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
|
||||
object = Z_OBJ(EX(This));
|
||||
}
|
||||
if (!object) {
|
||||
ce = object->ce;
|
||||
} else {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
/* Allowed for PHP 4 compatibility. */
|
||||
zend_error(
|
||||
@ -23969,6 +23975,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
|
||||
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zend_class_constant *c;
|
||||
zval *value;
|
||||
USE_OPLINE
|
||||
|
||||
@ -23978,7 +23985,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS
|
||||
if (IS_UNUSED == IS_CONST) {
|
||||
if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
|
||||
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
||||
ZVAL_DEREF(value);
|
||||
#ifdef ZTS
|
||||
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
||||
#endif
|
||||
@ -24006,13 +24012,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUS
|
||||
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
||||
}
|
||||
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
||||
ZVAL_DEREF(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
ZVAL_DEREF(value);
|
||||
if (EXPECTED((c = zend_hash_find_ptr(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
||||
if (!zend_verify_const_access(c, EG(scope))) {
|
||||
zend_throw_error(NULL, "Cannot access %s const %s::%s", zend_visibility_string(Z_ACCESS_FLAGS(c->value)), ZSTR_VAL(ce->name), Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
||||
HANDLE_EXCEPTION();
|
||||
}
|
||||
value = &c->value;
|
||||
if (Z_CONSTANT_P(value)) {
|
||||
EG(scope) = ce;
|
||||
zval_update_constant_ex(value, 1, NULL);
|
||||
@ -25234,8 +25243,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
|
||||
object = Z_OBJ(EX(This));
|
||||
}
|
||||
if (!object) {
|
||||
ce = object->ce;
|
||||
} else {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
/* Allowed for PHP 4 compatibility. */
|
||||
zend_error(
|
||||
@ -26592,8 +26601,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
|
||||
object = Z_OBJ(EX(This));
|
||||
}
|
||||
if (!object) {
|
||||
ce = object->ce;
|
||||
} else {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
/* Allowed for PHP 4 compatibility. */
|
||||
zend_error(
|
||||
@ -28225,8 +28234,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U
|
||||
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
||||
if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
|
||||
object = Z_OBJ(EX(This));
|
||||
}
|
||||
if (!object) {
|
||||
ce = object->ce;
|
||||
} else {
|
||||
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
||||
/* Allowed for PHP 4 compatibility. */
|
||||
zend_error(
|
||||
|
@ -324,11 +324,13 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
|
||||
|
||||
if (ce) {
|
||||
uint32_t tv = ZEND_RESULT(opline).var;
|
||||
zend_class_constant *cc;
|
||||
zval *c, t;
|
||||
|
||||
if ((c = zend_hash_find(&ce->constants_table,
|
||||
Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL) {
|
||||
ZVAL_DEREF(c);
|
||||
if ((cc = zend_hash_find_ptr(&ce->constants_table,
|
||||
Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL &&
|
||||
(Z_ACCESS_FLAGS(cc->value) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
|
||||
c = &cc->value;
|
||||
if (Z_TYPE_P(c) == IS_CONSTANT_AST) {
|
||||
break;
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
|
||||
{
|
||||
Bucket *p, *q, *end;
|
||||
zend_ulong nIndex;
|
||||
zend_class_constant *c;
|
||||
|
||||
ht->nTableSize = source->nTableSize;
|
||||
ht->nTableMask = source->nTableMask;
|
||||
@ -265,8 +266,14 @@ static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
|
||||
q->key = p->key;
|
||||
|
||||
/* Copy data */
|
||||
ZVAL_COPY_VALUE(&q->val, &p->val);
|
||||
zend_clone_zval(&q->val);
|
||||
c = ARENA_REALLOC(Z_PTR(p->val));
|
||||
ZVAL_PTR(&q->val, c);
|
||||
|
||||
zend_clone_zval(&c->value);
|
||||
if ((void*)c->ce >= ZCG(current_persistent_script)->arena_mem &&
|
||||
(void*)c->ce < (void*)((char*)ZCG(current_persistent_script)->arena_mem + ZCG(current_persistent_script)->arena_size)) {
|
||||
c->ce = ARENA_REALLOC(c->ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -508,6 +508,28 @@ static void zend_file_cache_serialize_prop_info(zval *zv,
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_file_cache_serialize_class_constant(zval *zv,
|
||||
zend_persistent_script *script,
|
||||
zend_file_cache_metainfo *info,
|
||||
void *buf)
|
||||
{
|
||||
if (!IS_SERIALIZED(Z_PTR_P(zv))) {
|
||||
zend_class_constant *c;
|
||||
|
||||
SERIALIZE_PTR(Z_PTR_P(zv));
|
||||
c = Z_PTR_P(zv);
|
||||
UNSERIALIZE_PTR(c);
|
||||
|
||||
zend_file_cache_serialize_zval(&c->value, script, info, buf);
|
||||
if (c->ce && !IS_SERIALIZED(c->ce)) {
|
||||
SERIALIZE_PTR(c->ce);
|
||||
}
|
||||
if (c->doc_comment && !IS_SERIALIZED(c->doc_comment)) {
|
||||
SERIALIZE_STR(c->doc_comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_file_cache_serialize_class(zval *zv,
|
||||
zend_persistent_script *script,
|
||||
zend_file_cache_metainfo *info,
|
||||
@ -545,7 +567,7 @@ static void zend_file_cache_serialize_class(zval *zv,
|
||||
p++;
|
||||
}
|
||||
}
|
||||
zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_zval);
|
||||
zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_class_constant);
|
||||
SERIALIZE_STR(ce->info.user.filename);
|
||||
SERIALIZE_STR(ce->info.user.doc_comment);
|
||||
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
|
||||
@ -1055,6 +1077,26 @@ static void zend_file_cache_unserialize_prop_info(zval *zv,
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_file_cache_unserialize_class_constant(zval *zv,
|
||||
zend_persistent_script *script,
|
||||
void *buf)
|
||||
{
|
||||
if (!IS_UNSERIALIZED(Z_PTR_P(zv))) {
|
||||
zend_class_constant *c;
|
||||
|
||||
UNSERIALIZE_PTR(Z_PTR_P(zv));
|
||||
c = Z_PTR_P(zv);
|
||||
|
||||
zend_file_cache_unserialize_class_constant(&c->value, script, buf);
|
||||
if (c->ce && !IS_UNSERIALIZED(c->ce)) {
|
||||
UNSERIALIZE_PTR(c->ce);
|
||||
}
|
||||
if (c->doc_comment && !IS_UNSERIALIZED(c->doc_comment)) {
|
||||
UNSERIALIZE_STR(c->doc_comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_file_cache_unserialize_class(zval *zv,
|
||||
zend_persistent_script *script,
|
||||
void *buf)
|
||||
@ -1090,7 +1132,7 @@ static void zend_file_cache_unserialize_class(zval *zv,
|
||||
}
|
||||
}
|
||||
zend_file_cache_unserialize_hash(&ce->constants_table,
|
||||
script, buf, zend_file_cache_unserialize_zval, NULL);
|
||||
script, buf, zend_file_cache_unserialize_class_constant, NULL);
|
||||
UNSERIALIZE_STR(ce->info.user.filename);
|
||||
UNSERIALIZE_STR(ce->info.user.doc_comment);
|
||||
zend_file_cache_unserialize_hash(&ce->properties_info,
|
||||
|
@ -716,6 +716,39 @@ static void zend_persist_property_info(zval *zv)
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_persist_class_constant(zval *zv)
|
||||
{
|
||||
zend_class_constant *c = zend_shared_alloc_get_xlat_entry(Z_PTR_P(zv));
|
||||
|
||||
if (c) {
|
||||
Z_PTR_P(zv) = c;
|
||||
return;
|
||||
}
|
||||
memcpy(ZCG(arena_mem), Z_PTR_P(zv), sizeof(zend_class_constant));
|
||||
zend_shared_alloc_register_xlat_entry(Z_PTR_P(zv), ZCG(arena_mem));
|
||||
c = Z_PTR_P(zv) = ZCG(arena_mem);
|
||||
ZCG(arena_mem) = (void*)((char*)ZCG(arena_mem) + ZEND_ALIGNED_SIZE(sizeof(zend_class_constant)));
|
||||
zend_persist_zval(&c->value);
|
||||
c->ce = zend_shared_alloc_get_xlat_entry(c->ce);
|
||||
if (c->doc_comment) {
|
||||
if (ZCG(accel_directives).save_comments) {
|
||||
zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
|
||||
if (doc_comment) {
|
||||
c->doc_comment = doc_comment;
|
||||
} else {
|
||||
zend_accel_store_string(c->doc_comment);
|
||||
}
|
||||
} else {
|
||||
zend_string *doc_comment = zend_shared_alloc_get_xlat_entry(c->doc_comment);
|
||||
if (!doc_comment) {
|
||||
zend_shared_alloc_register_xlat_entry(c->doc_comment, c->doc_comment);
|
||||
zend_string_release(c->doc_comment);
|
||||
}
|
||||
c->doc_comment = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_persist_class_entry(zval *zv)
|
||||
{
|
||||
zend_class_entry *ce = Z_PTR_P(zv);
|
||||
@ -745,7 +778,7 @@ static void zend_persist_class_entry(zval *zv)
|
||||
}
|
||||
ce->static_members_table = NULL;
|
||||
|
||||
zend_hash_persist(&ce->constants_table, zend_persist_zval);
|
||||
zend_hash_persist(&ce->constants_table, zend_persist_class_constant);
|
||||
|
||||
if (ce->info.user.filename) {
|
||||
/* do not free! PHP has centralized filename storage, compiler will free it */
|
||||
|
@ -292,6 +292,21 @@ static void zend_persist_property_info_calc(zval *zv)
|
||||
}
|
||||
}
|
||||
|
||||
static void zend_persist_class_constant_calc(zval *zv)
|
||||
{
|
||||
zend_class_constant *c = Z_PTR_P(zv);
|
||||
|
||||
if (!zend_shared_alloc_get_xlat_entry(c)) {
|
||||
zend_shared_alloc_register_xlat_entry(c, c);
|
||||
ADD_ARENA_SIZE(sizeof(zend_class_constant));
|
||||
zend_persist_zval_calc(&c->value);
|
||||
if (ZCG(accel_directives).save_comments && c->doc_comment) {
|
||||
ADD_STRING(c->doc_comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void zend_persist_class_entry_calc(zval *zv)
|
||||
{
|
||||
zend_class_entry *ce = Z_PTR_P(zv);
|
||||
@ -316,7 +331,7 @@ static void zend_persist_class_entry_calc(zval *zv)
|
||||
zend_persist_zval_calc(&ce->default_static_members_table[i]);
|
||||
}
|
||||
}
|
||||
zend_hash_persist_calc(&ce->constants_table, zend_persist_zval_calc);
|
||||
zend_hash_persist_calc(&ce->constants_table, zend_persist_class_constant_calc);
|
||||
|
||||
if (ce->info.user.filename) {
|
||||
ADD_STRING(ce->info.user.filename);
|
||||
|
@ -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);
|
||||
|
@ -15,7 +15,7 @@ Class [ <user> class Foo ] {
|
||||
@@ %s017.php 2-4
|
||||
|
||||
- Constants [1] {
|
||||
Constant [ string test ] { ok }
|
||||
Constant [ public string test ] { ok }
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
|
194
ext/reflection/tests/ReflectionClassConstant_basic1.phpt
Normal file
194
ext/reflection/tests/ReflectionClassConstant_basic1.phpt
Normal file
@ -0,0 +1,194 @@
|
||||
--TEST--
|
||||
Test usage of ReflectionClassConstant methods __toString(), export(), getName(), getValue(), isPublic(), isPrivate(), isProtected(), getModifiers(), getDeclaringClass() and getDocComment().
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function reflectClassConstant($base, $constant) {
|
||||
$constInfo = new ReflectionClassConstant($base, $constant);
|
||||
echo "**********************************\n";
|
||||
$class = is_object($base) ? get_class($base) : $base;
|
||||
echo "Reflecting on class constant $class::$constant\n\n";
|
||||
echo "__toString():\n";
|
||||
var_dump($constInfo->__toString());
|
||||
echo "export():\n";
|
||||
var_dump(ReflectionClassConstant::export($base, $constant, true));
|
||||
echo "export():\n";
|
||||
var_dump(ReflectionClassConstant::export($base, $constant, false));
|
||||
echo "getName():\n";
|
||||
var_dump($constInfo->getName());
|
||||
echo "getValue():\n";
|
||||
var_dump($constInfo->getValue());
|
||||
echo "isPublic():\n";
|
||||
var_dump($constInfo->isPublic());
|
||||
echo "isPrivate():\n";
|
||||
var_dump($constInfo->isPrivate());
|
||||
echo "isProtected():\n";
|
||||
var_dump($constInfo->isProtected());
|
||||
echo "getModifiers():\n";
|
||||
var_dump($constInfo->getModifiers());
|
||||
echo "getDeclaringClass():\n";
|
||||
var_dump($constInfo->getDeclaringClass());
|
||||
echo "getDocComment():\n";
|
||||
var_dump($constInfo->getDocComment());
|
||||
echo "\n**********************************\n";
|
||||
}
|
||||
|
||||
class TestClass {
|
||||
public const /** My Doc comment */ PUB = true;
|
||||
/** Another doc comment */
|
||||
protected const PROT = 4;
|
||||
private const PRIV = "keepOut";
|
||||
}
|
||||
$instance = new TestClass();
|
||||
|
||||
reflectClassConstant("TestClass", "PUB");
|
||||
reflectClassConstant("TestClass", "PROT");
|
||||
reflectClassConstant("TestClass", "PRIV");
|
||||
reflectClassConstant($instance, "PRIV");
|
||||
reflectClassConstant($instance, "BAD_CONST");
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::PUB
|
||||
|
||||
__toString():
|
||||
string(42) " Constant [ public boolean PUB ] { 1 }
|
||||
"
|
||||
export():
|
||||
string(42) " Constant [ public boolean PUB ] { 1 }
|
||||
"
|
||||
export():
|
||||
Constant [ public boolean PUB ] { 1 }
|
||||
|
||||
NULL
|
||||
getName():
|
||||
string(3) "PUB"
|
||||
getValue():
|
||||
bool(true)
|
||||
isPublic():
|
||||
bool(true)
|
||||
isPrivate():
|
||||
bool(false)
|
||||
isProtected():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(256)
|
||||
getDeclaringClass():
|
||||
object(ReflectionClass)#3 (1) {
|
||||
["name"]=>
|
||||
string(9) "TestClass"
|
||||
}
|
||||
getDocComment():
|
||||
string(21) "/** My Doc comment */"
|
||||
|
||||
**********************************
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::PROT
|
||||
|
||||
__toString():
|
||||
string(46) " Constant [ protected integer PROT ] { 4 }
|
||||
"
|
||||
export():
|
||||
string(46) " Constant [ protected integer PROT ] { 4 }
|
||||
"
|
||||
export():
|
||||
Constant [ protected integer PROT ] { 4 }
|
||||
|
||||
NULL
|
||||
getName():
|
||||
string(4) "PROT"
|
||||
getValue():
|
||||
int(4)
|
||||
isPublic():
|
||||
bool(false)
|
||||
isPrivate():
|
||||
bool(false)
|
||||
isProtected():
|
||||
bool(true)
|
||||
getModifiers():
|
||||
int(512)
|
||||
getDeclaringClass():
|
||||
object(ReflectionClass)#3 (1) {
|
||||
["name"]=>
|
||||
string(9) "TestClass"
|
||||
}
|
||||
getDocComment():
|
||||
string(26) "/** Another doc comment */"
|
||||
|
||||
**********************************
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::PRIV
|
||||
|
||||
__toString():
|
||||
string(49) " Constant [ private string PRIV ] { keepOut }
|
||||
"
|
||||
export():
|
||||
string(49) " Constant [ private string PRIV ] { keepOut }
|
||||
"
|
||||
export():
|
||||
Constant [ private string PRIV ] { keepOut }
|
||||
|
||||
NULL
|
||||
getName():
|
||||
string(4) "PRIV"
|
||||
getValue():
|
||||
string(7) "keepOut"
|
||||
isPublic():
|
||||
bool(false)
|
||||
isPrivate():
|
||||
bool(true)
|
||||
isProtected():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(1024)
|
||||
getDeclaringClass():
|
||||
object(ReflectionClass)#3 (1) {
|
||||
["name"]=>
|
||||
string(9) "TestClass"
|
||||
}
|
||||
getDocComment():
|
||||
bool(false)
|
||||
|
||||
**********************************
|
||||
**********************************
|
||||
Reflecting on class constant TestClass::PRIV
|
||||
|
||||
__toString():
|
||||
string(49) " Constant [ private string PRIV ] { keepOut }
|
||||
"
|
||||
export():
|
||||
string(49) " Constant [ private string PRIV ] { keepOut }
|
||||
"
|
||||
export():
|
||||
Constant [ private string PRIV ] { keepOut }
|
||||
|
||||
NULL
|
||||
getName():
|
||||
string(4) "PRIV"
|
||||
getValue():
|
||||
string(7) "keepOut"
|
||||
isPublic():
|
||||
bool(false)
|
||||
isPrivate():
|
||||
bool(true)
|
||||
isProtected():
|
||||
bool(false)
|
||||
getModifiers():
|
||||
int(1024)
|
||||
getDeclaringClass():
|
||||
object(ReflectionClass)#3 (1) {
|
||||
["name"]=>
|
||||
string(9) "TestClass"
|
||||
}
|
||||
getDocComment():
|
||||
bool(false)
|
||||
|
||||
**********************************
|
||||
|
||||
Fatal error: Uncaught ReflectionException: Class Constant TestClass::BAD_CONST does not exist in %s:%d
|
||||
Stack trace:
|
||||
#0 %s(%d): ReflectionClassConstant->__construct(Object(TestClass), 'BAD_CONST')
|
||||
#1 %s(%d): reflectClassConstant(Object(TestClass), 'BAD_CONST')
|
||||
#2 {main}
|
||||
thrown in %s on line %d
|
@ -12,9 +12,9 @@ echo $rc;
|
||||
Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||
|
||||
- Constants [3] {
|
||||
Constant [ integer IS_IMPLICIT_ABSTRACT ] { 16 }
|
||||
Constant [ integer IS_EXPLICIT_ABSTRACT ] { 32 }
|
||||
Constant [ integer IS_FINAL ] { 4 }
|
||||
Constant [ public integer IS_IMPLICIT_ABSTRACT ] { 16 }
|
||||
Constant [ public integer IS_EXPLICIT_ABSTRACT ] { 32 }
|
||||
Constant [ public integer IS_FINAL ] { 4 }
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
@ -34,7 +34,7 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||
Property [ <default> public $name ]
|
||||
}
|
||||
|
||||
- Methods [50] {
|
||||
- Methods [52] {
|
||||
Method [ <internal:Reflection> final private method __clone ] {
|
||||
|
||||
- Parameters [0] {
|
||||
@ -175,6 +175,12 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||
}
|
||||
}
|
||||
|
||||
Method [ <internal:Reflection> public method getReflectionConstants ] {
|
||||
|
||||
- Parameters [0] {
|
||||
}
|
||||
}
|
||||
|
||||
Method [ <internal:Reflection> public method getConstant ] {
|
||||
|
||||
- Parameters [1] {
|
||||
@ -182,6 +188,13 @@ Class [ <internal:Reflection> class ReflectionClass implements Reflector ] {
|
||||
}
|
||||
}
|
||||
|
||||
Method [ <internal:Reflection> public method getReflectionConstant ] {
|
||||
|
||||
- Parameters [1] {
|
||||
Parameter #0 [ <required> $name ]
|
||||
}
|
||||
}
|
||||
|
||||
Method [ <internal:Reflection> public method getInterfaces ] {
|
||||
|
||||
- Parameters [0] {
|
||||
|
@ -9,7 +9,7 @@ var_dump($ext->getClasses());
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECT--
|
||||
array(14) {
|
||||
array(15) {
|
||||
["ReflectionException"]=>
|
||||
object(ReflectionClass)#2 (1) {
|
||||
["name"]=>
|
||||
@ -70,13 +70,18 @@ array(14) {
|
||||
["name"]=>
|
||||
string(18) "ReflectionProperty"
|
||||
}
|
||||
["ReflectionExtension"]=>
|
||||
["ReflectionClassConstant"]=>
|
||||
object(ReflectionClass)#14 (1) {
|
||||
["name"]=>
|
||||
string(23) "ReflectionClassConstant"
|
||||
}
|
||||
["ReflectionExtension"]=>
|
||||
object(ReflectionClass)#15 (1) {
|
||||
["name"]=>
|
||||
string(19) "ReflectionExtension"
|
||||
}
|
||||
["ReflectionZendExtension"]=>
|
||||
object(ReflectionClass)#15 (1) {
|
||||
object(ReflectionClass)#16 (1) {
|
||||
["name"]=>
|
||||
string(23) "ReflectionZendExtension"
|
||||
}
|
||||
|
@ -20,11 +20,11 @@ Class [ <user> class just_constants ] {
|
||||
@@ %s %d-%d
|
||||
|
||||
- Constants [5] {
|
||||
Constant [ boolean BOOLEAN_CONSTANT ] { 1 }
|
||||
Constant [ null NULL_CONSTANT ] { }
|
||||
Constant [ string STRING_CONSTANT ] { This is a string }
|
||||
Constant [ integer INTEGER_CONSTANT ] { 1000 }
|
||||
Constant [ float FLOAT_CONSTANT ] { 3.14159265 }
|
||||
Constant [ public boolean BOOLEAN_CONSTANT ] { 1 }
|
||||
Constant [ public null NULL_CONSTANT ] { }
|
||||
Constant [ public string STRING_CONSTANT ] { This is a string }
|
||||
Constant [ public integer INTEGER_CONSTANT ] { 1000 }
|
||||
Constant [ public float FLOAT_CONSTANT ] { 3.14159265 }
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
|
@ -31,7 +31,7 @@ Object of class [ <user> class foo extends foo2 ] {
|
||||
@@ %s 7-21
|
||||
|
||||
- Constants [1] {
|
||||
Constant [ string BAR ] { foo's bar }
|
||||
Constant [ public string BAR ] { foo's bar }
|
||||
}
|
||||
|
||||
- Static properties [0] {
|
||||
|
34
tests/classes/constants_comments_001.phpt
Normal file
34
tests/classes/constants_comments_001.phpt
Normal file
@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
Class constants and doc comments
|
||||
--INI--
|
||||
opcache.save_comments=1
|
||||
--FILE--
|
||||
<?php
|
||||
class X {
|
||||
/** comment X1 */
|
||||
const X1 = 1;
|
||||
const X2 = 2;
|
||||
/** comment X3 */
|
||||
const X3 = 3;
|
||||
}
|
||||
class Y extends X {
|
||||
/** comment Y1 */
|
||||
const Y1 = 1;
|
||||
const Y2 = 2;
|
||||
/** comment Y3 */
|
||||
const Y3 = 3;
|
||||
}
|
||||
$r = new ReflectionClass('Y');
|
||||
foreach ($r->getReflectionConstants() as $rc) {
|
||||
echo $rc->getName() . " : " . $rc->getDocComment() . "\n";
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Y1 : /** comment Y1 */
|
||||
Y2 :
|
||||
Y3 : /** comment Y3 */
|
||||
X1 : /** comment X1 */
|
||||
X2 :
|
||||
X3 : /** comment X3 */
|
23
tests/classes/constants_visibility_001.phpt
Normal file
23
tests/classes/constants_visibility_001.phpt
Normal file
@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
Class public constant visibility
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public const publicConst = 'publicConst';
|
||||
static function staticConstDump() {
|
||||
var_dump(self::publicConst);
|
||||
}
|
||||
function constDump() {
|
||||
var_dump(self::publicConst);
|
||||
}
|
||||
}
|
||||
|
||||
var_dump(A::publicConst);
|
||||
A::staticConstDump();
|
||||
(new A())->constDump();
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(11) "publicConst"
|
||||
string(11) "publicConst"
|
||||
string(11) "publicConst"
|
30
tests/classes/constants_visibility_002.phpt
Normal file
30
tests/classes/constants_visibility_002.phpt
Normal file
@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Class protected constant visibility
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
protected const protectedConst = 'protectedConst';
|
||||
static function staticConstDump() {
|
||||
var_dump(self::protectedConst);
|
||||
}
|
||||
function constDump() {
|
||||
var_dump(self::protectedConst);
|
||||
}
|
||||
}
|
||||
|
||||
A::staticConstDump();
|
||||
(new A())->constDump();
|
||||
constant('A::protectedConst');
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(14) "protectedConst"
|
||||
string(14) "protectedConst"
|
||||
|
||||
Warning: constant(): Couldn't find constant A::protectedConst in %s on line 14
|
||||
|
||||
Fatal error: Uncaught Error: Cannot access protected const A::protectedConst in %s:14
|
||||
Stack trace:
|
||||
#0 %s(14): constant('A::protectedCon...')
|
||||
#1 {main}
|
||||
thrown in %s on line 14
|
30
tests/classes/constants_visibility_003.phpt
Normal file
30
tests/classes/constants_visibility_003.phpt
Normal file
@ -0,0 +1,30 @@
|
||||
--TEST--
|
||||
Class private constant visibility
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
private const privateConst = 'privateConst';
|
||||
static function staticConstDump() {
|
||||
var_dump(self::privateConst);
|
||||
}
|
||||
function constDump() {
|
||||
var_dump(self::privateConst);
|
||||
}
|
||||
}
|
||||
|
||||
A::staticConstDump();
|
||||
(new A())->constDump();
|
||||
constant('A::privateConst');
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(12) "privateConst"
|
||||
string(12) "privateConst"
|
||||
|
||||
Warning: constant(): Couldn't find constant A::privateConst in %s on line 14
|
||||
|
||||
Fatal error: Uncaught Error: Cannot access private const A::privateConst in %s:14
|
||||
Stack trace:
|
||||
#0 %s(14): constant('A::privateConst')
|
||||
#1 {main}
|
||||
thrown in %s on line 14
|
28
tests/classes/constants_visibility_004.phpt
Normal file
28
tests/classes/constants_visibility_004.phpt
Normal file
@ -0,0 +1,28 @@
|
||||
--TEST--
|
||||
Only public and protected class constants should be inherited
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
public const X = 1;
|
||||
protected const Y = 2;
|
||||
private const Z = 3;
|
||||
}
|
||||
class B extends A {
|
||||
static public function checkConstants() {
|
||||
var_dump(self::X);
|
||||
var_dump(self::Y);
|
||||
var_dump(self::Z);
|
||||
}
|
||||
}
|
||||
|
||||
B::checkConstants();
|
||||
?>
|
||||
--EXPECTF--
|
||||
int(1)
|
||||
int(2)
|
||||
|
||||
Fatal error: Uncaught Error: Undefined class constant 'Z' in %s:11
|
||||
Stack trace:
|
||||
#0 %s(15): B::checkConstants()
|
||||
#1 {main}
|
||||
thrown in %s on line 11
|
10
tests/classes/constants_visibility_005.phpt
Normal file
10
tests/classes/constants_visibility_005.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Static constants are not allowed
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
static const X = 1;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use 'static' as constant modifier in %s on line 3
|
11
tests/classes/constants_visibility_006.phpt
Normal file
11
tests/classes/constants_visibility_006.phpt
Normal file
@ -0,0 +1,11 @@
|
||||
--TEST--
|
||||
Abstract constants are not allowed
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
abstract const X = 1;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use 'abstract' as constant modifier in %s on line 3
|
||||
|
10
tests/classes/constants_visibility_007.phpt
Normal file
10
tests/classes/constants_visibility_007.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Final constants are not allowed
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
final const X = 1;
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Cannot use 'final' as constant modifier in %s on line 3
|
16
tests/classes/constants_visibility_error_001.phpt
Normal file
16
tests/classes/constants_visibility_error_001.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Class private constant visibility error
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
private const privateConst = 'privateConst';
|
||||
}
|
||||
|
||||
var_dump(A::privateConst);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Cannot access private const A::privateConst in %s:6
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line 6
|
16
tests/classes/constants_visibility_error_002.phpt
Normal file
16
tests/classes/constants_visibility_error_002.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Class protected constant visibility error
|
||||
--FILE--
|
||||
<?php
|
||||
class A {
|
||||
protected const protectedConst = 'protectedConst';
|
||||
}
|
||||
|
||||
var_dump(A::protectedConst);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
Fatal error: Uncaught Error: Cannot access protected const A::protectedConst in %s:6
|
||||
Stack trace:
|
||||
#0 {main}
|
||||
thrown in %s on line 6
|
16
tests/classes/constants_visibility_error_003.phpt
Normal file
16
tests/classes/constants_visibility_error_003.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
A redeclared class constant must have the same or higher visibility
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
public const publicConst = 0;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
protected const publicConst = 1;
|
||||
}
|
||||
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Access level to B::publicConst must be public (as in class A) in %s on line 9
|
16
tests/classes/constants_visibility_error_004.phpt
Normal file
16
tests/classes/constants_visibility_error_004.phpt
Normal file
@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
A redeclared class constant must have the same or higher visibility
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class A {
|
||||
protected const protectedConst = 0;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
private const protectedConst = 1;
|
||||
}
|
||||
|
||||
|
||||
--EXPECTF--
|
||||
Fatal error: Access level to B::protectedConst must be protected (as in class A) or weaker in %s on line 9
|
12
tests/classes/interface_constant_inheritance_005.phpt
Normal file
12
tests/classes/interface_constant_inheritance_005.phpt
Normal file
@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Ensure a interface can have public constants
|
||||
--FILE--
|
||||
<?php
|
||||
interface IA {
|
||||
public const FOO = 10;
|
||||
}
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
10
tests/classes/interface_constant_inheritance_006.phpt
Normal file
10
tests/classes/interface_constant_inheritance_006.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Ensure a interface can not have protected constants
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
interface A {
|
||||
protected const FOO = 10;
|
||||
}
|
||||
--EXPECTF--
|
||||
Fatal error: Access type for interface constant A::FOO must be public in %s on line 3
|
10
tests/classes/interface_constant_inheritance_007.phpt
Normal file
10
tests/classes/interface_constant_inheritance_007.phpt
Normal file
@ -0,0 +1,10 @@
|
||||
--TEST--
|
||||
Ensure a interface can not have private constants
|
||||
|
||||
--FILE--
|
||||
<?php
|
||||
interface A {
|
||||
private const FOO = 10;
|
||||
}
|
||||
--EXPECTF--
|
||||
Fatal error: Access type for interface constant A::FOO must be public in %s on line 3
|
Loading…
Reference in New Issue
Block a user