| 
42 | 42 | 
 
  | 
43 | 43 | #define R_SUB_CALLBACK_CLASS_TYPE 1  | 
44 | 44 | #define R_SUB_CALLBACK_FT_TYPE 2  | 
 | 45 | +#define R_SUB_CLOSURE_TYPE 3  | 
45 | 46 | 
 
  | 
46 | 47 | int le_redis_sock;  | 
47 | 48 | extern int le_redis_array;  | 
@@ -5278,21 +5279,23 @@ PHP_METHOD(Redis, publish)  | 
5278 | 5279 | 
 
  | 
5279 | 5280 | PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd)  | 
5280 | 5281 | {  | 
5281 |  | -	zval *z_callback,*object, *array, **data;  | 
 | 5282 | +	zval *object, *array, **data;  | 
5282 | 5283 |     HashTable *arr_hash;  | 
5283 | 5284 |     HashPosition pointer;  | 
5284 | 5285 |     RedisSock *redis_sock;  | 
5285 |  | -    char *cmd = "", *old_cmd = NULL, *callback_ft_name;  | 
5286 |  | -    int cmd_len, array_count, callback_ft_name_len;  | 
 | 5286 | +    char *cmd = "", *old_cmd = NULL;  | 
 | 5287 | +    int cmd_len, array_count;  | 
5287 | 5288 | 	zval *z_tab, **tmp;  | 
5288 | 5289 | 	char *type_response;  | 
5289 | 5290 | 
 
  | 
5290 |  | -	int callback_type = 0;  | 
5291 |  | -	zval *z_o, *z_fun = NULL,*z_ret, *z_args[4];  | 
5292 |  | -	char *method_name;  | 
 | 5291 | +	// Function call information  | 
 | 5292 | +	zend_fcall_info z_callback;  | 
 | 5293 | +	zend_fcall_info_cache z_callback_cache;  | 
 | 5294 | + | 
 | 5295 | +	zval *z_ret, **z_args[4];  | 
5293 | 5296 | 
 
  | 
5294 |  | -	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaz|z",   | 
5295 |  | -									 &object, redis_ce, &array, &z_callback) == FAILURE) {  | 
 | 5297 | +	if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oaf",  | 
 | 5298 | +									 &object, redis_ce, &array, &z_callback, &z_callback_cache) == FAILURE) {  | 
5296 | 5299 | 		RETURN_FALSE;	  | 
5297 | 5300 | 	}  | 
5298 | 5301 | 
 
  | 
@@ -5352,32 +5355,10 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd)  | 
5352 | 5355 | 	}  | 
5353 | 5356 | 	efree(z_tab);	  | 
5354 | 5357 | 
 
  | 
5355 |  | -	/* verify the callback */  | 
5356 |  | -	if(Z_TYPE_P(z_callback) == IS_ARRAY) {  | 
5357 |  | - | 
5358 |  | -        /* object */  | 
5359 |  | -		if (zend_hash_index_find(Z_ARRVAL_P(z_callback), 0, (void**)&tmp) == FAILURE) {  | 
5360 |  | -			RETURN_FALSE;  | 
5361 |  | -		}  | 
5362 |  | -		z_o = *tmp;  | 
5363 |  | - | 
5364 |  | -        /* method name */  | 
5365 |  | -		if (zend_hash_index_find(Z_ARRVAL_P(z_callback), 1, (void**)&tmp) == FAILURE) {  | 
5366 |  | -			RETURN_FALSE;  | 
5367 |  | -		}  | 
5368 |  | -		method_name = Z_STRVAL_PP(tmp);	  | 
5369 |  | - | 
5370 |  | -		ALLOC_INIT_ZVAL(z_fun);  | 
5371 |  | -		ZVAL_STRING(z_fun, method_name, 1);  | 
5372 |  | -		callback_type = R_SUB_CALLBACK_CLASS_TYPE;  | 
5373 |  | - | 
5374 |  | -	} else if(Z_TYPE_P(z_callback) == IS_STRING) {  | 
5375 |  | -		callback_ft_name = Z_STRVAL_P(z_callback);  | 
5376 |  | -		callback_ft_name_len = strlen(callback_ft_name);  | 
5377 |  | -		callback_type = R_SUB_CALLBACK_FT_TYPE;  | 
5378 |  | -		MAKE_STD_ZVAL(z_fun);  | 
5379 |  | -		ZVAL_STRINGL(z_fun, callback_ft_name, callback_ft_name_len, 0);  | 
5380 |  | -	}  | 
 | 5358 | +	// Set a pointer to our return value and to our arguments.  | 
 | 5359 | +	z_callback.retval_ptr_ptr = &z_ret;  | 
 | 5360 | +	z_callback.params = z_args;  | 
 | 5361 | +	z_callback.no_separation = 0;  | 
5381 | 5362 | 
 
  | 
5382 | 5363 | 	/* Multibulk Response, format : {message type, originating channel, message payload} */  | 
5383 | 5364 | 	while(1) {		  | 
@@ -5420,48 +5401,43 @@ PHPAPI void generic_subscribe_cmd(INTERNAL_FUNCTION_PARAMETERS, char *sub_cmd)  | 
5420 | 5401 | 		}  | 
5421 | 5402 | 
 
  | 
5422 | 5403 | 		// Always pass the Redis object through  | 
5423 |  | -		z_args[0] = getThis();  | 
 | 5404 | +		z_args[0] = &getThis();  | 
5424 | 5405 | 
 
  | 
5425 | 5406 | 		// Set up our callback args depending on the message type  | 
5426 | 5407 | 		if(is_pmsg) {  | 
5427 |  | -			z_args[1] = *pattern;  | 
5428 |  | -			z_args[2] = *channel;  | 
5429 |  | -			z_args[3] = *data;  | 
 | 5408 | +			z_args[1] = pattern;  | 
 | 5409 | +			z_args[2] = channel;  | 
 | 5410 | +			z_args[3] = data;  | 
5430 | 5411 | 		} else {  | 
5431 |  | -			z_args[1] = *channel;  | 
5432 |  | -			z_args[2] = *data;  | 
 | 5412 | +			z_args[1] = channel;  | 
 | 5413 | +			z_args[2] = data;  | 
5433 | 5414 | 		}  | 
5434 |  | -	  | 
5435 |  | -		switch(callback_type) {  | 
5436 |  | -			case R_SUB_CALLBACK_CLASS_TYPE:  | 
5437 |  | -		       	MAKE_STD_ZVAL(z_ret);  | 
5438 |  | -				call_user_function(&redis_ce->function_table, &z_o, z_fun, z_ret, tab_idx, z_args TSRMLS_CC);  | 
5439 |  | -		        efree(z_ret);  | 
5440 |  | -				break;  | 
5441 | 5415 | 
 
  | 
5442 |  | -			case R_SUB_CALLBACK_FT_TYPE:  | 
5443 |  | -		       	MAKE_STD_ZVAL(z_ret);  | 
5444 |  | -	        	call_user_function(EG(function_table), NULL, z_fun, z_ret, tab_idx, z_args TSRMLS_CC);  | 
5445 |  | -		        efree(z_ret);  | 
5446 |  | -				break;  | 
 | 5416 | +		// Set our argument information  | 
 | 5417 | +		z_callback.param_count = tab_idx;  | 
 | 5418 | + | 
 | 5419 | +		// Break if we can't call the function  | 
 | 5420 | +		if(zend_call_function(&z_callback, &z_callback_cache TSRMLS_CC) != SUCCESS) {  | 
 | 5421 | +			break;  | 
5447 | 5422 | 		}  | 
 | 5423 | + | 
 | 5424 | +		// If we have a return value, free it.  Note, we could use the return value to break the subscribe loop  | 
 | 5425 | +		if(z_ret) zval_ptr_dtor(&z_ret);  | 
 | 5426 | + | 
5448 | 5427 |         /* TODO: provide a way to break out of the loop. */  | 
5449 | 5428 | 		zval_dtor(z_tab);  | 
5450 | 5429 | 		efree(z_tab);  | 
5451 | 5430 | 	}  | 
5452 |  | - | 
5453 |  | -	// Free our function  | 
5454 |  | -	efree(z_fun);  | 
5455 | 5431 | }  | 
5456 | 5432 | 
 
  | 
5457 |  | -/* {{{ proto void Redis::psubscribe(Array(channel1, channel2, ... channelN))  | 
 | 5433 | +/* {{{ proto void Redis::psubscribe(Array(pattern1, pattern2, ... patternN))  | 
5458 | 5434 |  */  | 
5459 | 5435 | PHP_METHOD(Redis, psubscribe)  | 
5460 | 5436 | {  | 
5461 | 5437 | 	generic_subscribe_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "psubscribe");  | 
5462 | 5438 | }  | 
5463 | 5439 | 
 
  | 
5464 |  | -/* {{{ proto void Redis::psubscribe(Array(channel1, channel2, ... channelN))  | 
 | 5440 | +/* {{{ proto void Redis::subscribe(Array(channel1, channel2, ... channelN))  | 
5465 | 5441 |  */  | 
5466 | 5442 | PHP_METHOD(Redis, subscribe) {  | 
5467 | 5443 | 	generic_subscribe_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, "subscribe");  | 
 | 
0 commit comments