static PHP_METHOD(midgard_object_class, factory) { MidgardConnection *mgd = mgd_handle(TSRMLS_C); CHECK_MGD(mgd); char *class_name; int class_name_length; zval *zvalue = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &class_name, &class_name_length, &zvalue) == FAILURE) return; zend_class_entry **pce = NULL; if (zend_lookup_class_ex(class_name, class_name_length, 1, &pce TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not find %s class", class_name); return; } zend_class_entry *ce = *pce; object_init_ex(return_value, ce); /* Initialize new object for which QB has been created for */ /* Call class constructor on given instance */ if (zvalue == NULL) { zend_call_method_with_0_params(&return_value, ce, &ce->constructor, "__construct", NULL); } else { zend_call_method_with_1_params(&return_value, ce, &ce->constructor, "__construct", NULL, zvalue); } }
/* {{{ proto Closure Closure::bind(callable old, object to [, mixed scope]) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure, *new_closure; zend_class_entry *ce, *called_scope; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)Z_OBJ_P(zclosure); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (scope_arg != NULL) { /* scope argument was given */ if (Z_TYPE_P(scope_arg) == IS_OBJECT) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { zend_string *class_name = zval_get_string(scope_arg); if (zend_string_equals_literal(class_name, "static")) { ce = closure->func.common.scope; } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) { zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name)); zend_string_release(class_name); RETURN_NULL(); } zend_string_release(class_name); } if(ce && ce != closure->func.common.scope && ce->type == ZEND_INTERNAL_CLASS) { /* rebinding to internal class is not allowed */ zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s", ZSTR_VAL(ce->name)); return; } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } if (newthis) { called_scope = Z_OBJCE_P(newthis); } else { called_scope = ce; } zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); new_closure = (zend_closure *) Z_OBJ_P(return_value); /* Runtime cache relies on bound scope to be immutable, hence we need a separate rt cache in case scope changed */ if (ZEND_USER_CODE(closure->func.type) && (closure->func.common.scope != new_closure->func.common.scope || (closure->func.op_array.fn_flags & ZEND_ACC_NO_RT_ARENA))) { new_closure->func.op_array.run_time_cache = emalloc(new_closure->func.op_array.cache_size); memset(new_closure->func.op_array.run_time_cache, 0, new_closure->func.op_array.cache_size); new_closure->func.op_array.fn_flags |= ZEND_ACC_NO_RT_ARENA; } }
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] ) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) /* {{{ */ { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce, **ce_p; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (scope_arg != NULL) { /* scope argument was given */ if (IS_ZEND_STD_OBJECT(*scope_arg)) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { char *class_name; int class_name_len; zval tmp_zval; INIT_ZVAL(tmp_zval); if (Z_TYPE_P(scope_arg) == IS_STRING) { class_name = Z_STRVAL_P(scope_arg); class_name_len = Z_STRLEN_P(scope_arg); } else { tmp_zval = *scope_arg; zval_copy_ctor(&tmp_zval); convert_to_string(&tmp_zval); class_name = Z_STRVAL(tmp_zval); class_name_len = Z_STRLEN(tmp_zval); } if ((class_name_len == sizeof("static") - 1) && (memcmp("static", class_name, sizeof("static") - 1) == 0)) { ce = closure->func.common.scope; } else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) { zend_error(E_WARNING, "Class '%s' not found", class_name); zval_dtor(&tmp_zval); RETURN_NULL(); } else { ce = *ce_p; } zval_dtor(&tmp_zval); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC); }
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] ) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce, *called_scope; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)Z_OBJ_P(zclosure); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (scope_arg != NULL) { /* scope argument was given */ if (Z_TYPE_P(scope_arg) == IS_OBJECT) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { zend_string *class_name = zval_get_string(scope_arg); if (zend_string_equals_literal(class_name, "static")) { ce = closure->func.common.scope; } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) { zend_error(E_WARNING, "Class '%s' not found", class_name->val); zend_string_release(class_name); RETURN_NULL(); } zend_string_release(class_name); } if(ce && ce != closure->func.common.scope && ce->type == ZEND_INTERNAL_CLASS) { /* rebinding to internal class is not allowed */ zend_error(E_WARNING, "Cannot bind closure to scope of internal class %s", ce->name->val); return; } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } if (newthis) { called_scope = Z_OBJCE_P(newthis); } else { called_scope = ce; } zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); }
/* {{{ proto Closure Closure::bind(callable old, object to [, mixed scope]) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce, *called_scope; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { return; } closure = (zend_closure *)Z_OBJ_P(zclosure); if (scope_arg != NULL) { /* scope argument was given */ if (Z_TYPE_P(scope_arg) == IS_OBJECT) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { zend_string *tmp_class_name; zend_string *class_name = zval_get_tmp_string(scope_arg, &tmp_class_name); if (zend_string_equals_literal(class_name, "static")) { ce = closure->func.common.scope; } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1)) == NULL) { zend_error(E_WARNING, "Class '%s' not found", ZSTR_VAL(class_name)); zend_string_release_ex(class_name, 0); RETURN_NULL(); } zend_tmp_string_release(tmp_class_name); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } if (!zend_valid_closure_binding(closure, newthis, ce)) { return; } if (newthis) { called_scope = Z_OBJCE_P(newthis); } else { called_scope = ce; } zend_create_closure(return_value, &closure->func, ce, called_scope, newthis); }
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] ) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)Z_OBJ_P(zclosure); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (scope_arg != NULL) { /* scope argument was given */ if (IS_ZEND_STD_OBJECT(*scope_arg)) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { zend_string *class_name = zval_get_string(scope_arg); if ((class_name->len == sizeof("static") - 1) && (memcmp("static", class_name->val, sizeof("static") - 1) == 0)) { ce = closure->func.common.scope; } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1 TSRMLS_CC)) == NULL) { zend_error(E_WARNING, "Class '%s' not found", class_name->val); STR_RELEASE(class_name); RETURN_NULL(); } STR_RELEASE(class_name); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC); }
static int zephir_is_callable_check_class(const char *name, int name_len, zend_fcall_info_cache *fcc, int *strict_class, char **error) /* {{{ */ { int ret = 0; zend_class_entry *pce; char *lcname = zend_str_tolower_dup(name, name_len); *strict_class = 0; if (name_len == sizeof("self") - 1 && !memcmp(lcname, "self", sizeof("self") - 1)) { if (!EG(scope)) { if (error) *error = estrdup("cannot access self:: when no class scope is active"); } else { fcc->called_scope = EG(current_execute_data)->called_scope; if (!fcc->object) { fcc->object = Z_OBJ(EG(current_execute_data)->This); } ret = 1; } } else if (name_len == sizeof("parent") - 1 && !memcmp(lcname, "parent", sizeof("parent") - 1)) { if (!EG(scope)) { if (error) *error = estrdup("cannot access parent:: when no class scope is active"); } else if (!EG(scope)->parent) { if (error) *error = estrdup("cannot access parent:: when current class scope has no parent"); } else { fcc->called_scope = EG(current_execute_data)->called_scope; if (!fcc->object) { fcc->object = Z_OBJ(EG(current_execute_data)->This); } *strict_class = 1; ret = 1; } } else if (name_len == sizeof("static") - 1 && !memcmp(lcname, "static", sizeof("static") - 1)) { if (!EG(current_execute_data)->called_scope) { if (error) *error = estrdup("cannot access static:: when no class scope is active"); } else { fcc->called_scope = EG(current_execute_data)->called_scope; if (!fcc->object) { fcc->object = Z_OBJ(EG(current_execute_data)->This); } *strict_class = 1; ret = 1; } } else { zend_string *class_name; class_name = zend_string_init(name, name_len, 0); if ((pce = zend_lookup_class_ex(class_name, NULL, 1)) != NULL) { zend_class_entry *scope = EG(current_execute_data) ? EG(current_execute_data)->func->common.scope : NULL; fcc->calling_scope = pce; if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) && instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope TSRMLS_CC) && instanceof_function(scope, fcc->calling_scope TSRMLS_CC)) { fcc->object = Z_OBJ(EG(current_execute_data)->This); fcc->called_scope = fcc->object->ce; } else { fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope; } *strict_class = 1; ret = 1; } else { if (error) zephir_spprintf(error, 0, "class '%.*s' not found", name_len, name); } zend_string_free(class_name); } efree(lcname); return ret; }
/* {{{ proto Closure Closure::bind(Closure $old, object $to [, mixed $scope = "static" ] ) Create a closure from another one and bind to another object and scope */ ZEND_METHOD(Closure, bind) { zval *newthis, *zclosure, *scope_arg = NULL; zend_closure *closure; zend_class_entry *ce, **ce_p; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oo!|z", &zclosure, zend_ce_closure, &newthis, &scope_arg) == FAILURE) { RETURN_NULL(); } closure = (zend_closure *)zend_object_store_get_object(zclosure TSRMLS_CC); if ((newthis != NULL) && (closure->func.common.fn_flags & ZEND_ACC_STATIC)) { zend_error(E_WARNING, "Cannot bind an instance to a static closure"); } if (newthis == NULL && !(closure->func.common.fn_flags & ZEND_ACC_STATIC) && closure->func.common.scope && closure->func.type == ZEND_INTERNAL_FUNCTION) { zend_error(E_WARNING, "Cannot unbind $this of internal method"); return; } if (scope_arg != NULL) { /* scope argument was given */ if (IS_ZEND_STD_OBJECT(*scope_arg)) { ce = Z_OBJCE_P(scope_arg); } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { char *class_name; int class_name_len; zval tmp_zval; INIT_ZVAL(tmp_zval); if (Z_TYPE_P(scope_arg) == IS_STRING) { class_name = Z_STRVAL_P(scope_arg); class_name_len = Z_STRLEN_P(scope_arg); } else { tmp_zval = *scope_arg; zval_copy_ctor(&tmp_zval); convert_to_string(&tmp_zval); class_name = Z_STRVAL(tmp_zval); class_name_len = Z_STRLEN(tmp_zval); } if ((class_name_len == sizeof("static") - 1) && (memcmp("static", class_name, sizeof("static") - 1) == 0)) { ce = closure->func.common.scope; } else if (zend_lookup_class_ex(class_name, class_name_len, NULL, 1, &ce_p TSRMLS_CC) == FAILURE) { zend_error(E_WARNING, "Class '%s' not found", class_name); zval_dtor(&tmp_zval); RETURN_NULL(); } else { ce = *ce_p; } zval_dtor(&tmp_zval); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; } /* verify that we aren't binding internal function to a wrong scope */ if (closure->func.type == ZEND_INTERNAL_FUNCTION && closure->func.common.scope != NULL) { if (ce && !instanceof_function(ce, closure->func.common.scope TSRMLS_CC)) { zend_error(E_WARNING, "Cannot bind function %s::%s to scope class %s", closure->func.common.scope->name, closure->func.common.function_name, ce->name); return; } if (ce && newthis && (closure->func.common.fn_flags & ZEND_ACC_STATIC) == 0 && !instanceof_function(Z_OBJCE_P(newthis), closure->func.common.scope TSRMLS_CC)) { zend_error(E_WARNING, "Cannot bind internal method %s::%s() to object of class %s", closure->func.common.scope->name, closure->func.common.function_name, Z_OBJCE_P(newthis)->name); return; } } zend_create_closure(return_value, &closure->func, ce, newthis TSRMLS_CC); }
/* {{{ install_class */ static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC) { zend_class_entry* class_entry = cl.class_entry; zend_class_entry* parent = NULL; int status; /* Special case for mangled names. Mangled names are unique to a file. * There is no way two classes with the same mangled name will occur, * unless a file is included twice. And if in case, a file is included * twice, all mangled name conflicts can be ignored and the class redeclaration * error may be deferred till runtime of the corresponding DECLARE_CLASS * calls. */ if(cl.name_len != 0 && cl.name[0] == '\0') { if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) { return SUCCESS; } } if(lazy && cl.name_len != 0 && cl.name[0] != '\0') { status = zend_hash_add(APCG(lazy_class_table), cl.name, cl.name_len+1, &cl, sizeof(apc_class_t), NULL); if(status == FAILURE) { zend_error(E_ERROR, "Cannot redeclare class %s", cl.name); } return status; } class_entry = apc_copy_class_entry_for_execution(cl.class_entry, ctxt TSRMLS_CC); if (class_entry == NULL) return FAILURE; /* restore parent class pointer for compile-time inheritance */ if (cl.parent_name != NULL) { zend_class_entry** parent_ptr = NULL; /* * __autoload brings in the old issues with mixed inheritance. * When a statically inherited class triggers autoload, it runs * afoul of a potential require_once "parent.php" in the previous * line, which when executed provides the parent class, but right * now goes and hits __autoload which could fail. * * missing parent == re-compile. * * whether __autoload is enabled or not, because __autoload errors * cause php to die. * * Aside: Do NOT pass *strlen(cl.parent_name)+1* because * zend_lookup_class_ex does it internally anyway! */ status = zend_lookup_class_ex(cl.parent_name, strlen(cl.parent_name), #ifdef ZEND_ENGINE_2_4 NULL, #endif 0, &parent_ptr TSRMLS_CC); if (status == FAILURE) { if(APCG(report_autofilter)) { apc_warning("Dynamic inheritance detected for class %s" TSRMLS_CC, cl.name); } class_entry->parent = NULL; return status; } else { parent = *parent_ptr; class_entry->parent = parent; zend_do_inheritance(class_entry, parent TSRMLS_CC); } } status = zend_hash_add(EG(class_table), cl.name, cl.name_len+1, &class_entry, sizeof(zend_class_entry*), NULL); if (status == FAILURE) { apc_error("Cannot redeclare class %s" TSRMLS_CC, cl.name); } return status; }
static PHP_METHOD(midgard_object_class, factory) { MidgardConnection *mgd = mgd_handle(TSRMLS_C); CHECK_MGD(mgd); char *class_name; int class_name_length; zval *zvalue = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z", &class_name, &class_name_length, &zvalue) == FAILURE) return; zend_class_entry **pce = NULL; #if PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3 if (zend_lookup_class_ex(class_name, class_name_length, NULL, 1, &pce TSRMLS_CC) == FAILURE) { #else if (zend_lookup_class_ex(class_name, class_name_length, 1, &pce TSRMLS_CC) == FAILURE) { #endif php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not find %s class", class_name); return; } zend_class_entry *ce = *pce; object_init_ex(return_value, ce); /* Initialize new object for which QB has been created for */ /* Call class constructor on given instance */ if (zvalue == NULL) { zend_call_method_with_0_params(&return_value, ce, &ce->constructor, "__construct", NULL); } else { zend_call_method_with_1_params(&return_value, ce, &ce->constructor, "__construct", NULL, zvalue); } } ZEND_BEGIN_ARG_INFO_EX(arginfo_midgard_object_class_factory, 0, 0, 1) ZEND_ARG_INFO(0, classname) ZEND_ARG_INFO(0, id) ZEND_END_ARG_INFO() static PHP_METHOD(midgard_object_class, get_object_by_guid) { RETVAL_FALSE; MidgardConnection *mgd = mgd_handle(TSRMLS_C); CHECK_MGD(mgd); char *guid; int guid_length; const gchar *type_name; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &guid, &guid_length) == FAILURE) return; MidgardObject *object = midgard_schema_object_factory_get_object_by_guid(mgd, guid); if (!object) { php_midgard_error_exception_throw(mgd TSRMLS_CC); return; } type_name = G_OBJECT_TYPE_NAME(G_OBJECT(object)); zend_class_entry *ce = zend_fetch_class((gchar *)type_name, strlen(type_name), ZEND_FETCH_CLASS_AUTO TSRMLS_CC); if (ce == NULL) { php_error(E_WARNING, "Can not find %s class", type_name); return; } php_midgard_gobject_new_with_gobject(return_value, ce, G_OBJECT(object), TRUE TSRMLS_CC); }