mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Change get_class() so that it returns qualified names for namespaced
classes. *HEADS UP*: get_class_name() handler interface is changed, now it should allocate the space it returns with emalloc, and the users free it. If anyone has problems with it or has suggestions how to do it without this - please tell. Also: make function_exists() understand namespaces.
This commit is contained in:
parent
c5b1314e05
commit
ad01495a48
5 changed files with 87 additions and 24 deletions
12
Zend/zend.c
12
Zend/zend.c
|
@ -283,10 +283,10 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
|
|||
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
|
||||
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
|
||||
}
|
||||
if (class_name == NULL) {
|
||||
class_name = "Unknown Class";
|
||||
zend_printf("%s Object (", class_name?class_name:"Unknown Class");
|
||||
if(class_name) {
|
||||
efree(class_name);
|
||||
}
|
||||
zend_printf("%s Object (", class_name);
|
||||
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
|
||||
properties = Z_OBJPROP_P(expr);
|
||||
}
|
||||
|
@ -336,10 +336,10 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
|
|||
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
|
||||
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
|
||||
}
|
||||
if (class_name == NULL) {
|
||||
class_name = "Unknown Class";
|
||||
zend_printf("%s Object\n", class_name?class_name:"Unknown Class");
|
||||
if(class_name) {
|
||||
efree(class_name);
|
||||
}
|
||||
zend_printf("%s Object\n", class_name);
|
||||
if (Z_OBJ_HANDLER_P(expr, get_properties)) {
|
||||
properties = Z_OBJPROP_P(expr);
|
||||
}
|
||||
|
|
|
@ -1631,6 +1631,29 @@ ZEND_API char *zend_get_module_version(char *module_name)
|
|||
return module->version;
|
||||
}
|
||||
|
||||
ZEND_API void zend_make_full_classname(zend_class_entry *ce, char **name, zend_uint *name_len)
|
||||
{
|
||||
int len = ce->name_length;
|
||||
char *full_name;
|
||||
|
||||
if(ce->ns && ce->ns->name) {
|
||||
len += ce->ns->name_length + 2;
|
||||
}
|
||||
|
||||
*name = full_name = emalloc(len+1);
|
||||
*name_len = len;
|
||||
|
||||
if(ce->ns && ce->ns->name) {
|
||||
memcpy(full_name, ce->ns->name, ce->ns->name_length);
|
||||
full_name += ce->ns->name_length;
|
||||
*(full_name++) = ':';
|
||||
*(full_name++) = ':';
|
||||
}
|
||||
|
||||
memcpy(full_name, ce->name, ce->name_length);
|
||||
full_name[ce->name_length] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
|
|
@ -260,6 +260,8 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
|
|||
ZEND_API ZEND_FUNCTION(display_disabled_function);
|
||||
ZEND_API ZEND_FUNCTION(display_disabled_class);
|
||||
|
||||
ZEND_API void zend_make_full_classname(zend_class_entry *ce, char **name, zend_uint *name_len);
|
||||
|
||||
#if ZEND_DEBUG
|
||||
#define CHECK_ZVAL_STRING(z) \
|
||||
if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); }
|
||||
|
|
|
@ -516,8 +516,8 @@ ZEND_FUNCTION(defined)
|
|||
ZEND_FUNCTION(get_class)
|
||||
{
|
||||
zval **arg;
|
||||
char *name;
|
||||
zend_uint name_len;
|
||||
char *name = "";
|
||||
zend_uint name_len = 0;
|
||||
|
||||
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &arg)==FAILURE) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
|
@ -535,11 +535,15 @@ ZEND_FUNCTION(get_class)
|
|||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
name = ce->name;
|
||||
name_len = ce->name_length;
|
||||
}
|
||||
if(ce->ns) {
|
||||
zend_make_full_classname(ce, &name, &name_len);
|
||||
RETURN_STRINGL(name, name_len, 0);
|
||||
} else {
|
||||
RETURN_STRINGL(ce->name, ce->name_length, 1);
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_STRINGL(name, name_len, 1);
|
||||
RETURN_STRINGL(name, name_len, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -550,20 +554,21 @@ ZEND_FUNCTION(get_parent_class)
|
|||
{
|
||||
zval **arg;
|
||||
zend_class_entry *ce = NULL;
|
||||
char *name;
|
||||
zend_uint name_length;
|
||||
|
||||
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &arg)==FAILURE) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
}
|
||||
|
||||
if (Z_TYPE_PP(arg) == IS_OBJECT) {
|
||||
char *name;
|
||||
zend_uint name_length;
|
||||
|
||||
if (Z_OBJ_HT_PP(arg)->get_class_name
|
||||
&& Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
|
||||
RETURN_STRINGL(name, name_length, 1);
|
||||
RETURN_STRINGL(name, name_length, 0);
|
||||
} else if (Z_OBJ_HT_PP(arg)->get_class_entry && (ce = zend_get_class_entry(*arg TSRMLS_CC))) {
|
||||
RETURN_STRINGL(ce->name, ce->name_length, 1);
|
||||
zend_make_full_classname(ce, &name, &name_length);
|
||||
RETURN_STRINGL(name, name_length, 0);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
@ -578,7 +583,8 @@ ZEND_FUNCTION(get_parent_class)
|
|||
}
|
||||
|
||||
if (ce && ce->parent) {
|
||||
RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
|
||||
zend_make_full_classname(ce->parent, &name, &name_length);
|
||||
RETURN_STRINGL(name, name_length, 0);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
@ -846,7 +852,7 @@ ZEND_FUNCTION(function_exists)
|
|||
{
|
||||
zval **function_name;
|
||||
zend_function *func;
|
||||
char *lcname;
|
||||
char *lcname, *func_name, *func_name_end;
|
||||
zend_bool retval;
|
||||
|
||||
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) {
|
||||
|
@ -856,14 +862,45 @@ ZEND_FUNCTION(function_exists)
|
|||
lcname = estrndup((*function_name)->value.str.val, (*function_name)->value.str.len);
|
||||
zend_str_tolower(lcname, (*function_name)->value.str.len);
|
||||
|
||||
retval = (zend_hash_find(EG(function_table), lcname, (*function_name)->value.str.len+1, (void **)&func) == SUCCESS);
|
||||
func_name_end = lcname + (*function_name)->value.str.len;
|
||||
if((func_name = zend_memnstr(lcname, "::", sizeof("::")-1, func_name_end)) == NULL) {
|
||||
retval = (zend_hash_find(EG(function_table), lcname, (*function_name)->value.str.len+1, (void **)&func) == SUCCESS);
|
||||
} else {
|
||||
/* handle ::f case */
|
||||
if (func_name == lcname) {
|
||||
retval = (zend_hash_find(EG(function_table), lcname+sizeof("::")-1, (*function_name)->value.str.len-(sizeof("::")-1)+1, (void **)&func) == SUCCESS);
|
||||
} else {
|
||||
/* handle ns::f case */
|
||||
int ns_name_length = func_name - lcname;
|
||||
char *ns_name;
|
||||
zend_namespace **ns;
|
||||
|
||||
func_name += sizeof("::")-1;
|
||||
|
||||
if(func_name >= func_name_end) {
|
||||
/* ns:: case */
|
||||
retval = 0;
|
||||
} else {
|
||||
ns_name = estrndup(lcname, ns_name_length);
|
||||
|
||||
if (zend_hash_find(&EG(global_namespace_ptr)->class_table, ns_name, ns_name_length+1, (void **)&ns) == SUCCESS &&
|
||||
CLASS_IS_NAMESPACE(*ns) &&
|
||||
zend_hash_find(&(*ns)->function_table, func_name, func_name_end - func_name + 1, (void **)&func) == SUCCESS) {
|
||||
retval = 1;
|
||||
} else {
|
||||
retval = 0;
|
||||
}
|
||||
efree(ns_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
efree(lcname);
|
||||
|
||||
/*
|
||||
* A bit of a hack, but not a bad one: we see if the handler of the function
|
||||
* is actually one that displays "function is disabled" message.
|
||||
*/
|
||||
if (retval &&
|
||||
if (retval && func->type == ZEND_INTERNAL_FUNCTION &&
|
||||
func->internal_function.handler == zif_display_disabled_function) {
|
||||
retval = 0;
|
||||
}
|
||||
|
|
|
@ -795,18 +795,19 @@ zend_class_entry *zend_std_object_get_class(zval *object TSRMLS_DC)
|
|||
int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC)
|
||||
{
|
||||
zend_object *zobj;
|
||||
zend_class_entry *ce;
|
||||
zobj = Z_OBJ_P(object);
|
||||
|
||||
if (parent) {
|
||||
if (!zobj->ce->parent) {
|
||||
return FAILURE;
|
||||
}
|
||||
*class_name = zobj->ce->parent->name;
|
||||
*class_name_len = zobj->ce->parent->name_length;
|
||||
ce = zobj->ce->parent;
|
||||
} else {
|
||||
*class_name = zobj->ce->name;
|
||||
*class_name_len = zobj->ce->name_length;
|
||||
ce = zobj->ce;
|
||||
}
|
||||
|
||||
zend_make_full_classname(ce, class_name, class_name_len);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue