/* {{{ 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; 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); }
/* {{{ 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); }