mirror of
https://github.com/php-win-ext/phpredis.git
synced 2026-03-24 00:52:16 +01:00
Implement VLINKS command
This commit is contained in:
committed by
Michael Grunder
parent
ea11d62aec
commit
7f9b1f416e
@@ -2527,6 +2527,27 @@ cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
add_next_index_zval(&c->multi_resp, &z_ret);
|
||||
}
|
||||
|
||||
PHP_REDIS_API void
|
||||
cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx) {
|
||||
zval z_ret;
|
||||
|
||||
if (c->reply_len < 0) {
|
||||
CLUSTER_RETURN_FALSE(c);
|
||||
}
|
||||
|
||||
if (redis_read_vlinks_response(c->cmd_sock, &z_ret, c->reply_len, ctx)
|
||||
!= SUCCESS)
|
||||
{
|
||||
CLUSTER_RETURN_FALSE(c);
|
||||
}
|
||||
|
||||
if (CLUSTER_IS_ATOMIC(c)) {
|
||||
RETURN_ZVAL(&z_ret, 0, 1);
|
||||
} else {
|
||||
add_next_index_zval(&c->multi_resp, &z_ret);
|
||||
}
|
||||
}
|
||||
|
||||
/* XINFO */
|
||||
PHP_REDIS_API void
|
||||
cluster_xinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c, void *ctx)
|
||||
|
||||
@@ -450,6 +450,8 @@ PHP_REDIS_API void cluster_unsub_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster
|
||||
void *ctx);
|
||||
PHP_REDIS_API void cluster_vinfo_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
PHP_REDIS_API void cluster_vlinks_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
|
||||
PHP_REDIS_API void cluster_zrange_resp(INTERNAL_FUNCTION_PARAMETERS, redisCluster *c,
|
||||
void *ctx);
|
||||
|
||||
57
library.c
57
library.c
@@ -2623,6 +2623,63 @@ redis_vemb_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_read_vlinks_response(RedisSock *redis_sock, zval *z_ret,
|
||||
long long elements, void *ctx)
|
||||
{
|
||||
long long i;
|
||||
zval z_ele;
|
||||
int links;
|
||||
|
||||
array_init_size(z_ret, elements);
|
||||
|
||||
for (i = 0; i < elements; i++) {
|
||||
if (read_mbulk_header(redis_sock, &links) < 0)
|
||||
return FAILURE;
|
||||
|
||||
array_init(&z_ele);
|
||||
redis_mbulk_reply_loop(redis_sock, &z_ele, links, UNSERIALIZE_KEYS);
|
||||
|
||||
if (ctx == PHPREDIS_CTX_PTR) {
|
||||
array_zip_values_and_scores(redis_sock, &z_ele, SCORE_DECODE_DOUBLE);
|
||||
}
|
||||
|
||||
add_next_index_zval(z_ret, &z_ele);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_vlinks_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, void *ctx)
|
||||
{
|
||||
int elements;
|
||||
zval z_ret;
|
||||
|
||||
ZVAL_FALSE(&z_ret);
|
||||
|
||||
if (read_mbulk_header(redis_sock, &elements) < 0)
|
||||
goto fail;
|
||||
|
||||
/* TODO: Figure out if we want `false` or `[]` here */
|
||||
if (elements < 0) {
|
||||
REDIS_RETURN_ZVAL(redis_sock, z_tab, z_ret);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (redis_read_vlinks_response(redis_sock, &z_ret, elements, ctx) != SUCCESS)
|
||||
goto fail;
|
||||
|
||||
REDIS_RETURN_ZVAL(redis_sock, z_tab, z_ret);
|
||||
return SUCCESS;
|
||||
|
||||
fail:
|
||||
zval_dtor(&z_ret);
|
||||
REDIS_RESPONSE_ERROR(redis_sock, z_tab);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
PHP_REDIS_API int
|
||||
redis_xinfo_reply(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
zval *z_tab, void *ctx)
|
||||
|
||||
@@ -133,6 +133,11 @@ PHP_REDIS_API int redis_vemb_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
PHP_REDIS_API int redis_read_vemb_response(RedisSock *redis_sock, zval *z_ret,
|
||||
long long count);
|
||||
|
||||
PHP_REDIS_API int redis_read_vlinks_response(RedisSock *redis_sock, zval *z_ret,
|
||||
long long elements, void *ctx);
|
||||
PHP_REDIS_API int redis_vlinks_reply(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
|
||||
PHP_REDIS_API int redis_pubsub_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
RedisSock *redis_sock, zval *z_tab, void *ctx);
|
||||
PHP_REDIS_API int redis_subscribe_response(INTERNAL_FUNCTION_PARAMETERS,
|
||||
|
||||
4
redis.c
4
redis.c
@@ -3213,6 +3213,10 @@ PHP_METHOD(Redis, vsetattr) {
|
||||
REDIS_PROCESS_CMD(vsetattr, redis_long_response);
|
||||
}
|
||||
|
||||
PHP_METHOD(Redis, vlinks) {
|
||||
REDIS_PROCESS_CMD(vlinks, redis_vlinks_reply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Streams
|
||||
*/
|
||||
|
||||
@@ -4312,6 +4312,17 @@ class Redis {
|
||||
*/
|
||||
public function vsetattr(string $key, mixed $member, array|string $attributes): Redis|int|false;
|
||||
|
||||
/**
|
||||
* Get any adajcent values for a member of a vector set.
|
||||
*
|
||||
* @param string $key The vector set to query.
|
||||
* @param mixed $member The member to query.
|
||||
* @param bool $withscores If set to `true`, the scores of the adjacent values will be returned.
|
||||
*
|
||||
* @return Redis|array|false An array of adjacent values and their scores, or false on failure.
|
||||
*/
|
||||
public function vlinks(string $key, mixed $member, bool $withscores = false): Redis|array|false;
|
||||
|
||||
/**
|
||||
* Truncate a STREAM key in various ways.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 4f62aadbf7d71be1cff70adecdb4e9565acb9d35 */
|
||||
* Stub hash: b946fc56310f3c069255e85b0fd733f96232c933 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 1, "null")
|
||||
@@ -1104,6 +1104,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_vsetattr, 0, 3,
|
||||
ZEND_ARG_TYPE_MASK(0, attributes, MAY_BE_ARRAY|MAY_BE_STRING, NULL)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_vlinks, 0, 2, Redis, MAY_BE_ARRAY|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, member, IS_MIXED, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, withscores, _IS_BOOL, 0, "false")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_Redis_xtrim, 0, 2, Redis, MAY_BE_LONG|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, threshold, IS_STRING, 0)
|
||||
@@ -1521,6 +1527,7 @@ ZEND_METHOD(Redis, vemb);
|
||||
ZEND_METHOD(Redis, vrandmember);
|
||||
ZEND_METHOD(Redis, vrem);
|
||||
ZEND_METHOD(Redis, vsetattr);
|
||||
ZEND_METHOD(Redis, vlinks);
|
||||
ZEND_METHOD(Redis, xtrim);
|
||||
ZEND_METHOD(Redis, zAdd);
|
||||
ZEND_METHOD(Redis, zCard);
|
||||
@@ -1806,6 +1813,7 @@ static const zend_function_entry class_Redis_methods[] = {
|
||||
ZEND_ME(Redis, vrandmember, arginfo_class_Redis_vrandmember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vrem, arginfo_class_Redis_vrem, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vsetattr, arginfo_class_Redis_vsetattr, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vlinks, arginfo_class_Redis_vlinks, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, xtrim, arginfo_class_Redis_xtrim, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, zAdd, arginfo_class_Redis_zAdd, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, zCard, arginfo_class_Redis_zCard, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -3213,6 +3213,10 @@ PHP_METHOD(RedisCluster, vrem) {
|
||||
CLUSTER_PROCESS_KW_CMD("VREM", redis_kv_cmd, cluster_long_resp, 0);
|
||||
}
|
||||
|
||||
PHP_METHOD(RedisCluster, vlinks) {
|
||||
CLUSTER_PROCESS_CMD(vlinks, cluster_vlinks_resp, 1);
|
||||
}
|
||||
|
||||
/* {{{ proto long RedisCluster::xack(string key, string group, array ids) }}} */
|
||||
PHP_METHOD(RedisCluster, xack) {
|
||||
CLUSTER_PROCESS_CMD(xack, cluster_long_resp, 0);
|
||||
|
||||
@@ -1103,6 +1103,11 @@ class RedisCluster {
|
||||
*/
|
||||
public function vrem(string $key, mixed $member): RedisCluster|int|false;
|
||||
|
||||
/**
|
||||
* @see Redis::vlinks
|
||||
*/
|
||||
public function vlinks(string $key, mixed $member, bool $withscores = false): RedisCluster|array|false;
|
||||
|
||||
/**
|
||||
* @see Redis::xack
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 3711907dacfa040f9670181e005bd8daaec146af */
|
||||
* Stub hash: 62909e1180a5d48d447f8de46ae3a70f60e7d6bb */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 1)
|
||||
@@ -914,6 +914,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_vrem, 0,
|
||||
ZEND_ARG_TYPE_INFO(0, member, IS_MIXED, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_vlinks, 0, 2, RedisCluster, MAY_BE_ARRAY|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, member, IS_MIXED, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, withscores, _IS_BOOL, 0, "false")
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_class_RedisCluster_xack, 0, 3, RedisCluster, MAY_BE_LONG|MAY_BE_FALSE)
|
||||
ZEND_ARG_TYPE_INFO(0, key, IS_STRING, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, group, IS_STRING, 0)
|
||||
@@ -1354,6 +1360,7 @@ ZEND_METHOD(RedisCluster, vinfo);
|
||||
ZEND_METHOD(RedisCluster, vemb);
|
||||
ZEND_METHOD(RedisCluster, vrandmember);
|
||||
ZEND_METHOD(RedisCluster, vrem);
|
||||
ZEND_METHOD(RedisCluster, vlinks);
|
||||
ZEND_METHOD(RedisCluster, xack);
|
||||
ZEND_METHOD(RedisCluster, xadd);
|
||||
ZEND_METHOD(RedisCluster, xclaim);
|
||||
@@ -1606,6 +1613,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
|
||||
ZEND_ME(RedisCluster, vemb, arginfo_class_RedisCluster_vemb, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vrandmember, arginfo_class_RedisCluster_vrandmember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vrem, arginfo_class_RedisCluster_vrem, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vlinks, arginfo_class_RedisCluster_vlinks, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xack, arginfo_class_RedisCluster_xack, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xadd, arginfo_class_RedisCluster_xadd, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xclaim, arginfo_class_RedisCluster_xclaim, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 3711907dacfa040f9670181e005bd8daaec146af */
|
||||
* Stub hash: 62909e1180a5d48d447f8de46ae3a70f60e7d6bb */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster___construct, 0, 0, 1)
|
||||
ZEND_ARG_INFO(0, name)
|
||||
@@ -771,6 +771,12 @@ ZEND_END_ARG_INFO()
|
||||
|
||||
#define arginfo_class_RedisCluster_vrem arginfo_class_RedisCluster_hexists
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_vlinks, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, member)
|
||||
ZEND_ARG_INFO(0, withscores)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_RedisCluster_xack, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, group)
|
||||
@@ -1186,6 +1192,7 @@ ZEND_METHOD(RedisCluster, vinfo);
|
||||
ZEND_METHOD(RedisCluster, vemb);
|
||||
ZEND_METHOD(RedisCluster, vrandmember);
|
||||
ZEND_METHOD(RedisCluster, vrem);
|
||||
ZEND_METHOD(RedisCluster, vlinks);
|
||||
ZEND_METHOD(RedisCluster, xack);
|
||||
ZEND_METHOD(RedisCluster, xadd);
|
||||
ZEND_METHOD(RedisCluster, xclaim);
|
||||
@@ -1438,6 +1445,7 @@ static const zend_function_entry class_RedisCluster_methods[] = {
|
||||
ZEND_ME(RedisCluster, vemb, arginfo_class_RedisCluster_vemb, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vrandmember, arginfo_class_RedisCluster_vrandmember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vrem, arginfo_class_RedisCluster_vrem, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, vlinks, arginfo_class_RedisCluster_vlinks, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xack, arginfo_class_RedisCluster_xack, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xadd, arginfo_class_RedisCluster_xadd, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(RedisCluster, xclaim, arginfo_class_RedisCluster_xclaim, ZEND_ACC_PUBLIC)
|
||||
|
||||
@@ -7039,6 +7039,36 @@ redis_vemb_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
redis_vlinks_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
{
|
||||
zend_bool withscores = false;
|
||||
smart_string cmdstr = {0};
|
||||
zend_string *key;
|
||||
zval *member;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(2, 3) {
|
||||
Z_PARAM_STR(key)
|
||||
Z_PARAM_ZVAL(member)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_BOOL(withscores)
|
||||
} ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
|
||||
|
||||
REDIS_CMD_INIT_SSTR_STATIC(&cmdstr, 2 + !!withscores, "VLINKS");
|
||||
redis_cmd_append_sstr_key_zstr(&cmdstr, key, redis_sock, slot);
|
||||
redis_cmd_append_sstr_zval(&cmdstr, member, redis_sock);
|
||||
if (withscores) {
|
||||
REDIS_CMD_APPEND_SSTR_STATIC(&cmdstr, "WITHSCORES");
|
||||
*ctx = PHPREDIS_CTX_PTR;
|
||||
}
|
||||
|
||||
*cmd = cmdstr.c;
|
||||
*cmd_len = cmdstr.len;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
redis_vsetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx)
|
||||
|
||||
@@ -355,6 +355,9 @@ int redis_vemb_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
int redis_vsetattr_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_vlinks_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
int redis_xadd_cmd(INTERNAL_FUNCTION_PARAMETERS, RedisSock *redis_sock,
|
||||
char **cmd, int *cmd_len, short *slot, void **ctx);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 4f62aadbf7d71be1cff70adecdb4e9565acb9d35 */
|
||||
* Stub hash: b946fc56310f3c069255e85b0fd733f96232c933 */
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis___construct, 0, 0, 0)
|
||||
ZEND_ARG_INFO(0, options)
|
||||
@@ -978,6 +978,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_vsetattr, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, attributes)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_vlinks, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, member)
|
||||
ZEND_ARG_INFO(0, withscores)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Redis_xtrim, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, key)
|
||||
ZEND_ARG_INFO(0, threshold)
|
||||
@@ -1356,6 +1362,7 @@ ZEND_METHOD(Redis, vemb);
|
||||
ZEND_METHOD(Redis, vrandmember);
|
||||
ZEND_METHOD(Redis, vrem);
|
||||
ZEND_METHOD(Redis, vsetattr);
|
||||
ZEND_METHOD(Redis, vlinks);
|
||||
ZEND_METHOD(Redis, xtrim);
|
||||
ZEND_METHOD(Redis, zAdd);
|
||||
ZEND_METHOD(Redis, zCard);
|
||||
@@ -1641,6 +1648,7 @@ static const zend_function_entry class_Redis_methods[] = {
|
||||
ZEND_ME(Redis, vrandmember, arginfo_class_Redis_vrandmember, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vrem, arginfo_class_Redis_vrem, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vsetattr, arginfo_class_Redis_vsetattr, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, vlinks, arginfo_class_Redis_vlinks, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, xtrim, arginfo_class_Redis_xtrim, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, zAdd, arginfo_class_Redis_zAdd, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(Redis, zCard, arginfo_class_Redis_zCard, ZEND_ACC_PUBLIC)
|
||||
|
||||
Reference in New Issue
Block a user