diff --git a/library.c b/library.c index 80ea088..0473f32 100644 --- a/library.c +++ b/library.c @@ -2749,6 +2749,80 @@ PHP_REDIS_API void redis_debug_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock } } +PHP_REDIS_API int +redis_sock_configure(RedisSock *redis_sock, HashTable *opts) +{ + zend_string *zkey; + zval *val; + + ZEND_HASH_FOREACH_STR_KEY_VAL(opts, zkey, val) { + if (zkey == NULL) { + continue; + } + ZVAL_DEREF(val); + if (zend_string_equals_literal_ci(zkey, "host")) { + if (Z_TYPE_P(val) != IS_STRING) { + REDIS_VALUE_EXCEPTION("Invalid host"); + return FAILURE; + } + if (redis_sock->host) zend_string_release(redis_sock->host); + redis_sock->host = zval_get_string(val); + } else if (zend_string_equals_literal_ci(zkey, "port")) { + if (Z_TYPE_P(val) != IS_LONG) { + REDIS_VALUE_EXCEPTION("Invalid port"); + return FAILURE; + } + redis_sock->port = zval_get_long(val); + } else if (zend_string_equals_literal_ci(zkey, "connectTimeout")) { + if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { + REDIS_VALUE_EXCEPTION("Invalid connect timeout"); + return FAILURE; + } + redis_sock->timeout = zval_get_double(val); + } else if (zend_string_equals_literal_ci(zkey, "readTimeout")) { + if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { + REDIS_VALUE_EXCEPTION("Invalid read timeout"); + return FAILURE; + } + redis_sock->read_timeout = zval_get_double(val); + } else if (zend_string_equals_literal_ci(zkey, "persistent")) { + if (Z_TYPE_P(val) == IS_STRING) { + if (redis_sock->persistent_id) zend_string_release(redis_sock->persistent_id); + redis_sock->persistent_id = zval_get_string(val); + redis_sock->persistent = 1; + } else { + redis_sock->persistent = zval_is_true(val); + } + } else if (zend_string_equals_literal_ci(zkey, "retryInterval")) { + if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { + REDIS_VALUE_EXCEPTION("Invalid retry interval"); + return FAILURE; + } + redis_sock->retry_interval = zval_get_long(val); + } else if (zend_string_equals_literal_ci(zkey, "ssl")) { + if (redis_sock_set_stream_context(redis_sock, val) != SUCCESS) { + REDIS_VALUE_EXCEPTION("Invalid SSL context options"); + return FAILURE; + } + } else if (zend_string_equals_literal_ci(zkey, "auth")) { + if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_ARRAY) { + REDIS_VALUE_EXCEPTION("Invalid auth credentials"); + return FAILURE; + } + redis_sock_set_auth_zval(redis_sock, val); + } else if (zend_string_equals_literal_ci(zkey, "backoff")) { + if (redis_sock_set_backoff(redis_sock, val) != SUCCESS) { + REDIS_VALUE_EXCEPTION("Invalid backoff options"); + return FAILURE; + } + } else { + php_error_docref(NULL, E_WARNING, "Skip unknown option '%s'", ZSTR_VAL(zkey)); + } + } ZEND_HASH_FOREACH_END(); + + return SUCCESS; +} + /** * redis_sock_create */ diff --git a/library.h b/library.h index f1601e9..d93ce05 100644 --- a/library.h +++ b/library.h @@ -75,6 +75,7 @@ PHP_REDIS_API void redis_parse_info_response(char *response, zval *z_ret); PHP_REDIS_API void redis_parse_client_list_response(char *response, zval *z_ret); PHP_REDIS_API int redis_type_response(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock, zval *z_tab, void *ctx); PHP_REDIS_API RedisSock* redis_sock_create(char *host, int host_len, int port, double timeout, double read_timeout, int persistent, char *persistent_id, long retry_interval); +PHP_REDIS_API int redis_sock_configure(RedisSock *redis_sock, HashTable *opts); PHP_REDIS_API int redis_sock_connect(RedisSock *redis_sock); PHP_REDIS_API int redis_sock_server_open(RedisSock *redis_sock); PHP_REDIS_API int redis_sock_auth(RedisSock *redis_sock); diff --git a/redis.c b/redis.c index 121e896..1a451af 100644 --- a/redis.c +++ b/redis.c @@ -455,83 +455,19 @@ PHP_MINFO_FUNCTION(redis) Public constructor */ PHP_METHOD(Redis, __construct) { + HashTable *opts = NULL; redis_object *redis; - zend_string *zkey; - zval *val, *opts = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|a", &opts) == FAILURE) { + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_NULL(opts) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_THROWS()); + + redis = PHPREDIS_ZVAL_GET_OBJECT(redis_object, getThis()); + redis->sock = redis_sock_create(ZEND_STRL("127.0.0.1"), 6379, 0, 0, 0, NULL, 0); + if (opts != NULL && redis_sock_configure(redis->sock, opts) != SUCCESS) { RETURN_THROWS(); } - - if (opts != NULL) { - redis = PHPREDIS_ZVAL_GET_OBJECT(redis_object, getThis()); - redis->sock = redis_sock_create("127.0.0.1", sizeof("127.0.0.1") - 1, 6379, 0, 0, 0, NULL, 0); - - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(opts), zkey, val) { - if (zkey == NULL) { - continue; - } - ZVAL_DEREF(val); - if (zend_string_equals_literal_ci(zkey, "host")) { - if (Z_TYPE_P(val) != IS_STRING) { - REDIS_VALUE_EXCEPTION("Invalid host"); - RETURN_THROWS(); - } - zend_string_release(redis->sock->host); - redis->sock->host = zval_get_string(val); - } else if (zend_string_equals_literal_ci(zkey, "port")) { - if (Z_TYPE_P(val) != IS_LONG) { - REDIS_VALUE_EXCEPTION("Invalid port"); - RETURN_THROWS(); - } - redis->sock->port = zval_get_long(val); - } else if (zend_string_equals_literal_ci(zkey, "connectTimeout")) { - if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { - REDIS_VALUE_EXCEPTION("Invalid connect timeout"); - RETURN_THROWS(); - } - redis->sock->timeout = zval_get_double(val); - } else if (zend_string_equals_literal_ci(zkey, "readTimeout")) { - if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { - REDIS_VALUE_EXCEPTION("Invalid read timeout"); - RETURN_THROWS(); - } - redis->sock->read_timeout = zval_get_double(val); - } else if (zend_string_equals_literal_ci(zkey, "persistent")) { - if (Z_TYPE_P(val) == IS_STRING) { - if (redis->sock->persistent_id) zend_string_release(redis->sock->persistent_id); - redis->sock->persistent_id = zval_get_string(val); - redis->sock->persistent = 1; - } else { - redis->sock->persistent = zval_is_true(val); - } - } else if (zend_string_equals_literal_ci(zkey, "retryInterval")) { - if (Z_TYPE_P(val) != IS_LONG && Z_TYPE_P(val) != IS_DOUBLE) { - REDIS_VALUE_EXCEPTION("Invalid retry interval"); - RETURN_THROWS(); - } - redis->sock->retry_interval = zval_get_long(val); - } else if (zend_string_equals_literal_ci(zkey, "ssl")) { - if (redis_sock_set_stream_context(redis->sock, val) != SUCCESS) { - REDIS_VALUE_EXCEPTION("Invalid SSL context options"); - RETURN_THROWS(); - } - } else if (zend_string_equals_literal_ci(zkey, "auth")) { - if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_ARRAY) { - REDIS_VALUE_EXCEPTION("Invalid auth credentials"); - RETURN_THROWS(); - } - redis_sock_set_auth_zval(redis->sock, val); - } else if (zend_string_equals_literal_ci(zkey, "backoff")) { - if (redis_sock_set_backoff(redis->sock, val) != SUCCESS) { - REDIS_VALUE_EXCEPTION("Invalid backoff options"); - RETURN_THROWS(); - } - } else { - php_error_docref(NULL, E_WARNING, "Skip unknown option '%s'", ZSTR_VAL(zkey)); - } - } ZEND_HASH_FOREACH_END(); - } } /* }}} */ diff --git a/redis_sentinel.c b/redis_sentinel.c index 1a4a05f..fdaa191 100644 --- a/redis_sentinel.c +++ b/redis_sentinel.c @@ -41,61 +41,20 @@ PHP_MINIT_FUNCTION(redis_sentinel) PHP_METHOD(RedisSentinel, __construct) { - int persistent = 0; - char *persistent_id = NULL; - double timeout = 0.0, read_timeout = 0.0; - zend_long port = 26379, retry_interval = 0; - redis_sentinel_object *obj; - zend_string *host; - zval *auth = NULL, *context = NULL, *zv = NULL; + HashTable *opts = NULL; + redis_sentinel_object *sentinel; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|ldz!ldza", - &host, &port, &timeout, &zv, - &retry_interval, &read_timeout, - &auth, &context) == FAILURE) { - RETURN_FALSE; - } + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_NULL(opts) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_THROWS()); - if (port < 0 || port > UINT16_MAX) { - REDIS_VALUE_EXCEPTION("Invalid port"); + sentinel = PHPREDIS_ZVAL_GET_OBJECT(redis_sentinel_object, getThis()); + sentinel->sock = redis_sock_create(ZEND_STRL("127.0.0.1"), 26379, 0, 0, 0, NULL, 0); + if (opts != NULL && redis_sock_configure(sentinel->sock, opts) != SUCCESS) { RETURN_THROWS(); } - - if (timeout > INT_MAX) { - REDIS_VALUE_EXCEPTION("Invalid connect timeout"); - RETURN_THROWS(); - } - - if (read_timeout > INT_MAX) { - REDIS_VALUE_EXCEPTION("Invalid read timeout"); - RETURN_THROWS(); - } - - if (retry_interval < 0L || retry_interval > INT_MAX) { - REDIS_VALUE_EXCEPTION("Invalid retry interval"); - RETURN_THROWS(); - } - - if (zv) { - ZVAL_DEREF(zv); - if (Z_TYPE_P(zv) == IS_STRING) { - persistent_id = Z_STRVAL_P(zv); - persistent = 1; /* even empty */ - } else { - persistent = zval_is_true(zv); - } - } - - obj = PHPREDIS_ZVAL_GET_OBJECT(redis_sentinel_object, getThis()); - obj->sock = redis_sock_create(ZSTR_VAL(host), ZSTR_LEN(host), port, - timeout, read_timeout, persistent, persistent_id, retry_interval); - if (auth) { - redis_sock_set_auth_zval(obj->sock, auth); - } - if (context) { - redis_sock_set_stream_context(obj->sock, context); - } - obj->sock->sentinel = 1; + sentinel->sock->sentinel = 1; } PHP_METHOD(RedisSentinel, ckquorum) diff --git a/redis_sentinel.h b/redis_sentinel.h index 0878b62..19a86cc 100644 --- a/redis_sentinel.h +++ b/redis_sentinel.h @@ -3,7 +3,7 @@ #include "sentinel_library.h" -#define PHP_REDIS_SENTINEL_VERSION "0.1" +#define PHP_REDIS_SENTINEL_VERSION "1.0" extern zend_class_entry *redis_sentinel_ce; extern PHP_MINIT_FUNCTION(redis_sentinel); diff --git a/redis_sentinel.stub.php b/redis_sentinel.stub.php index 6ec54d8..486ac43 100644 --- a/redis_sentinel.stub.php +++ b/redis_sentinel.stub.php @@ -8,7 +8,7 @@ class RedisSentinel { - public function __construct(string $host, int $port = 26379, float $timeout = 0, mixed $persistent = null, int $retry_interval = 0, float $read_timeout = 0, #[\SensitiveParameter] mixed $auth = null, array $context = null); + public function __construct(array $options = null); /** @return bool|RedisSentinel */ public function ckquorum(string $master); diff --git a/redis_sentinel_arginfo.h b/redis_sentinel_arginfo.h index 43c57e9..e917b7d 100644 --- a/redis_sentinel_arginfo.h +++ b/redis_sentinel_arginfo.h @@ -1,15 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 847c735dfbbb643366344acfe6e2c5e8b76d0520 */ + * Stub hash: f1f746cc848b1debcdf88eae015732720ba206c8 */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 1) - ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "26379") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_DOUBLE, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, persistent, IS_MIXED, 0, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, retry_interval, IS_LONG, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, read_timeout, IS_DOUBLE, 0, "0") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, auth, IS_MIXED, 0, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, context, IS_ARRAY, 0, "null") +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel_ckquorum, 0, 0, 1) @@ -77,11 +70,6 @@ static zend_class_entry *register_class_RedisSentinel(void) INIT_CLASS_ENTRY(ce, "RedisSentinel", class_RedisSentinel_methods); class_entry = zend_register_internal_class_ex(&ce, NULL); -#if (PHP_VERSION_ID >= 80200) - - - zend_add_parameter_attribute(zend_hash_str_find_ptr(&class_entry->function_table, "__construct", sizeof("__construct") - 1), 6, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); -#endif return class_entry; } diff --git a/redis_sentinel_legacy_arginfo.h b/redis_sentinel_legacy_arginfo.h index 07f34be..5f7a70d 100644 --- a/redis_sentinel_legacy_arginfo.h +++ b/redis_sentinel_legacy_arginfo.h @@ -1,15 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 847c735dfbbb643366344acfe6e2c5e8b76d0520 */ + * Stub hash: f1f746cc848b1debcdf88eae015732720ba206c8 */ -ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 1) - ZEND_ARG_INFO(0, host) - ZEND_ARG_INFO(0, port) - ZEND_ARG_INFO(0, timeout) - ZEND_ARG_INFO(0, persistent) - ZEND_ARG_INFO(0, retry_interval) - ZEND_ARG_INFO(0, read_timeout) - ZEND_ARG_INFO(0, auth) - ZEND_ARG_INFO(0, context) +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel___construct, 0, 0, 0) + ZEND_ARG_INFO(0, options) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisSentinel_ckquorum, 0, 0, 1) diff --git a/tests/RedisSentinelTest.php b/tests/RedisSentinelTest.php index 2d188b3..0fdc3a9 100644 --- a/tests/RedisSentinelTest.php +++ b/tests/RedisSentinelTest.php @@ -30,7 +30,7 @@ class Redis_Sentinel_Test extends TestSuite protected function newInstance() { - return new RedisSentinel($this->getHost()); + return new RedisSentinel(['host' => $this->getHost()]); } public function setUp()