Browse Source

Support redis user password auth and tls encryption

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
tags/v23.0.0beta1
John Molakvoæ (skjnldsv) 2 years ago
parent
commit
ed10d85ff3
No account linked to committer's email address
5 changed files with 241 additions and 159 deletions
  1. 0
    4
      build/psalm-baseline.xml
  2. 102
    110
      build/stubs/redis.php
  3. 35
    23
      build/stubs/redis_cluster.php
  4. 20
    0
      config/config.sample.php
  5. 84
    22
      lib/private/RedisFactory.php

+ 0
- 4
build/psalm-baseline.xml View File

</ForbiddenCode> </ForbiddenCode>
</file> </file>
<file src="lib/private/RedisFactory.php"> <file src="lib/private/RedisFactory.php">
<InvalidPropertyAssignmentValue occurrences="2">
<code>new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout)</code>
<code>new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $config['password'])</code>
</InvalidPropertyAssignmentValue>
<InvalidScalarArgument occurrences="1"> <InvalidScalarArgument occurrences="1">
<code>\RedisCluster::OPT_SLAVE_FAILOVER</code> <code>\RedisCluster::OPT_SLAVE_FAILOVER</code>
</InvalidScalarArgument> </InvalidScalarArgument>

+ 102
- 110
build/stubs/redis.php View File

<?php <?php


use JetBrains\PhpStorm\Deprecated;

/** /**
* Helper autocomplete for php redis extension * Helper autocomplete for php redis extension
* *
const SCAN_NORETRY = 0; const SCAN_NORETRY = 0;
const SCAN_RETRY = 1; const SCAN_RETRY = 1;


/**
* @since 5.3.0
*/
const SCAN_PREFIX = 2;

/**
* @since 5.3.0
*/
const SCAN_NOPREFIX = 3;

/** /**
* Serializers * Serializers
*/ */
const COMPRESSION_NONE = 0; const COMPRESSION_NONE = 0;
const COMPRESSION_LZF = 1; const COMPRESSION_LZF = 1;
const COMPRESSION_ZSTD = 2; const COMPRESSION_ZSTD = 2;
const COMPRESSION_LZ4 = 3;


/** /**
* Compression ZSTD levels * Compression ZSTD levels
/** /**
* Connects to a Redis instance. * Connects to a Redis instance.
* *
* @param string $host can be a host, or the path to a unix domain socket
* @param int $port optional
* @param float $timeout value in seconds (optional, default is 0.0 meaning unlimited)
* @param null $reserved should be null if $retryInterval is specified
* @param int $retryInterval retry interval in milliseconds.
* @param float $readTimeout value in seconds (optional, default is 0 meaning unlimited)
* @param string $host can be a host, or the path to a unix domain socket
* @param int $port optional
* @param float $timeout value in seconds (optional, default is 0.0 meaning unlimited)
* @param null $reserved should be null if $retryInterval is specified
* @param int $retryInterval retry interval in milliseconds.
* @param float $readTimeout value in seconds (optional, default is 0 meaning unlimited)
* @param array $connectionParameters extra config to send to redis
* *
* @return bool TRUE on success, FALSE on error * @return bool TRUE on success, FALSE on error
* *
$timeout = 0.0, $timeout = 0.0,
$reserved = null, $reserved = null,
$retryInterval = 0, $retryInterval = 0,
$readTimeout = 0.0
$readTimeout = 0.0,
$connectionParameters = []
) { ) {
} }


* @param float $readTimeout value in seconds (optional, default is 0 meaning unlimited) * @param float $readTimeout value in seconds (optional, default is 0 meaning unlimited)
* *
* @return bool TRUE on success, FALSE on error * @return bool TRUE on success, FALSE on error
*
* @see connect()
* @deprecated use Redis::connect()
*/ */
#[Deprecated(replacement: '%class%->connect(%parametersList%)')]
public function open( public function open(
$host, $host,
$port = 6379, $port = 6379,
/** /**
* Retrieve our host or unix socket that we're connected to * Retrieve our host or unix socket that we're connected to
* *
* @return string|bool The host or unix socket we're connected to or FALSE if we're not connected
* @return string|false The host or unix socket we're connected to or FALSE if we're not connected
*/ */
public function getHost() public function getHost()
{ {
/** /**
* Get the port we're connected to * Get the port we're connected to
* *
* @return int|bool Returns the port we're connected to or FALSE if we're not connected
* @return int|false Returns the port we're connected to or FALSE if we're not connected
*/ */
public function getPort() public function getPort()
{ {
/** /**
* Get the (write) timeout in use for phpredis * Get the (write) timeout in use for phpredis
* *
* @return float|bool The timeout (DOUBLE) specified in our connect call or FALSE if we're not connected
* @return float|false The timeout (DOUBLE) specified in our connect call or FALSE if we're not connected
*/ */
public function getTimeout() public function getTimeout()
{ {
* @param float $readTimeout * @param float $readTimeout
* *
* @return bool * @return bool
*
* @deprecated use Redis::pconnect()
* @see pconnect()
*/ */
#[Deprecated(replacement: '%class%->pconnect(%parametersList%)')]
public function popen( public function popen(
$host, $host,
$port = 6379, $port = 6379,
/** /**
* Check the current connection status * Check the current connection status
* *
* @param string $message
* @param string $message [optional]
* *
* @return bool|string TRUE if the command is successful or returns message * @return bool|string TRUE if the command is successful or returns message
* Throws a RedisException object on connectivity error, as described above. * Throws a RedisException object on connectivity error, as described above.
* @throws RedisException * @throws RedisException
* @link https://redis.io/commands/ping * @link https://redis.io/commands/ping
*/ */
public function ping($message)
public function ping($message = null)
{ {
} }


* *
* @param string $key * @param string $key
* *
* @return string|mixed|bool If key didn't exist, FALSE is returned.
* @return string|mixed|false If key didn't exist, FALSE is returned.
* Otherwise, the value related to this key is returned * Otherwise, the value related to this key is returned
* *
* @link https://redis.io/commands/get * @link https://redis.io/commands/get
} }


/** /**
* @see del()
* @deprecated use Redis::del()
*
* @param string|string[] $key1 * @param string|string[] $key1
* @param string $key2 * @param string $key2
* @param string $key3 * @param string $key3
* *
* @return int Number of keys deleted * @return int Number of keys deleted
*/ */
#[Deprecated(replacement: "%class%->del(%parametersList%)")]
public function delete($key1, $key2 = null, $key3 = null) public function delete($key1, $key2 = null, $key3 = null)
{ {
} }
* a Redis::PIPELINE block is simply transmitted faster to the server, but without any guarantee of atomicity. * a Redis::PIPELINE block is simply transmitted faster to the server, but without any guarantee of atomicity.
* discard cancels a transaction. * discard cancels a transaction.
* *
* @return Redis returns the Redis instance and enters multi-mode.
* @return static returns the Redis instance and enters multi-mode.
* Once in multi-mode, all subsequent method calls return the same object until exec() is called. * Once in multi-mode, all subsequent method calls return the same object until exec() is called.
* *
* @link https://redis.io/commands/multi * @link https://redis.io/commands/multi
* If the key exists and is not a list, FALSE is returned. * If the key exists and is not a list, FALSE is returned.
* *
* @param string $key * @param string $key
* @param string|mixed $value1... Variadic list of values to push in key, if dont used serialized, used string
* @param string|mixed ...$value1 Variadic list of values to push in key, if dont used serialized, used string
* *
* @return int|bool The new length of the list in case of success, FALSE in case of Failure
* @return int|false The new length of the list in case of success, FALSE in case of Failure
* *
* @link https://redis.io/commands/lpush * @link https://redis.io/commands/lpush
* @example * @example
* If the key exists and is not a list, FALSE is returned. * If the key exists and is not a list, FALSE is returned.
* *
* @param string $key * @param string $key
* @param string|mixed $value1... Variadic list of values to push in key, if dont used serialized, used string
* @param string|mixed ...$value1 Variadic list of values to push in key, if dont used serialized, used string
* *
* @return int|bool The new length of the list in case of success, FALSE in case of Failure
* @return int|false The new length of the list in case of success, FALSE in case of Failure
* *
* @link https://redis.io/commands/rpush * @link https://redis.io/commands/rpush
* @example * @example
* @param string $key * @param string $key
* @param string|mixed $value String, value to push in key * @param string|mixed $value String, value to push in key
* *
* @return int|bool The new length of the list in case of success, FALSE in case of Failure.
* @return int|false The new length of the list in case of success, FALSE in case of Failure.
* *
* @link https://redis.io/commands/lpushx * @link https://redis.io/commands/lpushx
* @example * @example
* @param string $key * @param string $key
* @param string|mixed $value String, value to push in key * @param string|mixed $value String, value to push in key
* *
* @return int|bool The new length of the list in case of success, FALSE in case of Failure.
* @return int|false The new length of the list in case of success, FALSE in case of Failure.
* *
* @link https://redis.io/commands/rpushx * @link https://redis.io/commands/rpushx
* @example * @example
} }


/** /**
* @see lLen()
* @link https://redis.io/commands/llen * @link https://redis.io/commands/llen
* @deprecated use Redis::lLen()
* *
* @param string $key * @param string $key
* *
* @return int The size of the list identified by Key exists * @return int The size of the list identified by Key exists
*/ */
#[Deprecated(replacement: '%class%->lLen(%parametersList%)')]
public function lSize($key) public function lSize($key)
{ {
} }
} }


/** /**
* @see lIndex()
* @link https://redis.io/commands/lindex * @link https://redis.io/commands/lindex
* @deprecated use Redis::lIndex()
* *
* @param string $key * @param string $key
* @param int $index * @param int $index
* @return mixed|bool the element at this index * @return mixed|bool the element at this index
*/ */
#[Deprecated(replacement: '%class%->lIndex(%parametersList%)')]
public function lGet($key, $index) public function lGet($key, $index)
{ {
} }
} }


/** /**
* @see lRange()
* @link https://redis.io/commands/lrange * @link https://redis.io/commands/lrange
* @deprecated use Redis::lRange()
* *
* @param string $key * @param string $key
* @param int $start * @param int $start
* @param int $end * @param int $end
* @return array * @return array
*/ */
#[Deprecated(replacement: '%class%->lRange(%parametersList%)')]
public function lGetRange($key, $start, $end) public function lGetRange($key, $start, $end)
{ {
} }
* @param int $start * @param int $start
* @param int $stop * @param int $stop
* *
* @return array|bool Bool return FALSE if the key identify a non-list value
* @return array|false Bool return FALSE if the key identify a non-list value
* *
* @link https://redis.io/commands/ltrim * @link https://redis.io/commands/ltrim
* @example * @example
} }


/** /**
* @see lTrim()
* @link https://redis.io/commands/ltrim * @link https://redis.io/commands/ltrim
* @deprecated use Redis::lTrim()
* *
* @param string $key * @param string $key
* @param int $start * @param int $start
* @param int $stop * @param int $stop
*/ */
#[Deprecated(replacement: '%class%->lTrim(%parametersList%)')]
public function listTrim($key, $start, $stop) public function listTrim($key, $start, $stop)
{ {
} }
} }


/** /**
* @see lRem
* @link https://redis.io/commands/lremove * @link https://redis.io/commands/lremove
* @deprecated use Redis::lRem()
* *
* @param string $key * @param string $key
* @param string $value * @param string $value
* @param int $count * @param int $count
*/ */
#[Deprecated(replacement: '%class%->lRem(%parametersList%)')]
public function lRemove($key, $value, $count) public function lRemove($key, $value, $count)
{ {
} }
} }


/** /**
* @see sRem()
* @link https://redis.io/commands/srem * @link https://redis.io/commands/srem
* @deprecated use Redis::sRem()
* *
* @param string $key * @param string $key
* @param string|mixed ...$member1 * @param string|mixed ...$member1
*/ */
#[Deprecated(replacement: '%class%->sRem(%parametersList%)')]
public function sRemove($key, ...$member1) public function sRemove($key, ...$member1)
{ {
} }
} }


/** /**
* @see sIsMember()
* @link https://redis.io/commands/sismember * @link https://redis.io/commands/sismember
* @deprecated use Redis::sIsMember()
* *
* @param string $key * @param string $key
* @param string|mixed $value * @param string|mixed $value
*/ */
#[Deprecated(replacement: '%class%->sIsMember(%parametersList%)')]
public function sContains($key, $value) public function sContains($key, $value)
{ {
} }
* @param string $key1 keys identifying the different sets on which we will apply the intersection. * @param string $key1 keys identifying the different sets on which we will apply the intersection.
* @param string ...$otherKeys variadic list of keys * @param string ...$otherKeys variadic list of keys
* *
* @return array contain the result of the intersection between those keys
* @return array|false contain the result of the intersection between those keys
* If the intersection between the different sets is empty, the return value will be empty array. * If the intersection between the different sets is empty, the return value will be empty array.
* *
* @link https://redis.io/commands/sinter * @link https://redis.io/commands/sinter
* @param string $key1 keys identifying the different sets on which we will apply the intersection. * @param string $key1 keys identifying the different sets on which we will apply the intersection.
* @param string ...$otherKeys variadic list of keys * @param string ...$otherKeys variadic list of keys
* *
* @return int|bool The cardinality of the resulting set, or FALSE in case of a missing key
* @return int|false The cardinality of the resulting set, or FALSE in case of a missing key
* *
* @link https://redis.io/commands/sinterstore * @link https://redis.io/commands/sinterstore
* @example * @example
* @param string $key1 first key for diff * @param string $key1 first key for diff
* @param string ...$otherKeys variadic list of keys corresponding to sets in redis * @param string ...$otherKeys variadic list of keys corresponding to sets in redis
* *
* @return int|bool The cardinality of the resulting set, or FALSE in case of a missing key
* @return int|false The cardinality of the resulting set, or FALSE in case of a missing key
* *
* @link https://redis.io/commands/sdiffstore * @link https://redis.io/commands/sdiffstore
* @example * @example
} }


/** /**
* @see sMembers()
* @link https://redis.io/commands/smembers * @link https://redis.io/commands/smembers
* @deprecated use Redis::sMembers()
* *
* @param string $key * @param string $key
* @return array An array of elements, the contents of the set * @return array An array of elements, the contents of the set
*/ */
#[Deprecated(replacement: '%class%->sMembers(%parametersList%)')]
public function sGetMembers($key) public function sGetMembers($key)
{ {
} }
* Scan a set for members * Scan a set for members
* *
* @param string $key The set to search. * @param string $key The set to search.
* @param int $iterator LONG (reference) to the iterator as we go.
* @param int &$iterator LONG (reference) to the iterator as we go.
* @param string $pattern String, optional pattern to match against. * @param string $pattern String, optional pattern to match against.
* @param int $count How many members to return at a time (Redis might return a different amount) * @param int $count How many members to return at a time (Redis might return a different amount)
* *
* @return array|bool PHPRedis will return an array of keys or FALSE when we're done iterating
* @return array|false PHPRedis will return an array of keys or FALSE when we're done iterating
* *
* @link https://redis.io/commands/sscan * @link https://redis.io/commands/sscan
* @example * @example
} }


/** /**
* @see rename()
* @link https://redis.io/commands/rename * @link https://redis.io/commands/rename
* @deprecated use Redis::rename()
* *
* @param string $srcKey * @param string $srcKey
* @param string $dstKey * @param string $dstKey
*/ */
#[Deprecated(replacement: '%class%->rename(%parametersList%)')]
public function renameKey($srcKey, $dstKey) public function renameKey($srcKey, $dstKey)
{ {
} }
} }


/** /**
* @see expire()
* @link https://redis.io/commands/expire * @link https://redis.io/commands/expire
* @deprecated use Redis::expire()
* *
* @param string $key * @param string $key
* @param int $ttl * @param int $ttl
* @return bool * @return bool
*/ */
#[Deprecated(replacement: '%class%->expire(%parametersList%)')]
public function setTimeout($key, $ttl) public function setTimeout($key, $ttl)
{ {
} }
} }


/** /**
* @see keys()
* @deprecated use Redis::keys()
*
* @param string $pattern * @param string $pattern
* @link https://redis.io/commands/keys * @link https://redis.io/commands/keys
*/ */
#[Deprecated(replacement: '%class%->keys(%parametersList%)')]
public function getKeys($pattern) public function getKeys($pattern)
{ {
} }
* Authenticate the connection using a password. * Authenticate the connection using a password.
* Warning: The password is sent in plain-text over the network. * Warning: The password is sent in plain-text over the network.
* *
* @param string $password
* @param string|string[] $password
* *
* @return bool TRUE if the connection is authenticated, FALSE otherwise * @return bool TRUE if the connection is authenticated, FALSE otherwise
* *
* @param string $string * @param string $string
* @param string $key * @param string $key
* *
* @return string|int|bool for "encoding", int for "refcount" and "idletime", FALSE if the key doesn't exist.
* @return string|int|false for "encoding", int for "refcount" and "idletime", FALSE if the key doesn't exist.
* *
* @link https://redis.io/commands/object * @link https://redis.io/commands/object
* @example * @example
/** /**
* Return a substring of a larger string * Return a substring of a larger string
* *
* @deprecated
* @param string $key * @param string $key
* @param int $start * @param int $start
* @param int $end * @param int $end
*/ */
#[Deprecated]
public function substr($key, $start, $end) public function substr($key, $start, $end)
{ {
} }
* - vm_enabled * - vm_enabled
* - role * - role
* *
* @return string
* @return array
* *
* @link https://redis.io/commands/info * @link https://redis.io/commands/info
* @example * @example
* *
* @return array Array containing the values related to keys in argument * @return array Array containing the values related to keys in argument
* *
* @deprecated use Redis::mGet()
* @example * @example
* <pre> * <pre>
* $redis->set('key1', 'value1'); * $redis->set('key1', 'value1');
* $redis->getMultiple(array('key0', 'key1', 'key5')); // array(`FALSE`, 'value2', `FALSE`); * $redis->getMultiple(array('key0', 'key1', 'key5')); // array(`FALSE`, 'value2', `FALSE`);
* </pre> * </pre>
*/ */
#[Deprecated(replacement: '%class%->mGet(%parametersList%)')]
public function getMultiple(array $keys) public function getMultiple(array $keys)
{ {
} }
* @param string $srcKey * @param string $srcKey
* @param string $dstKey * @param string $dstKey
* *
* @return string|mixed|bool The element that was moved in case of success, FALSE in case of failure.
* @return string|mixed|false The element that was moved in case of success, FALSE in case of failure.
* *
* @link https://redis.io/commands/rpoplpush * @link https://redis.io/commands/rpoplpush
* @example * @example
* @link https://redis.io/commands/zadd * @link https://redis.io/commands/zadd
* @example * @example
* <pre> * <pre>
* <pre>
* $redis->zAdd('z', 1, 'v1', 2, 'v2', 3, 'v3', 4, 'v4' ); // int(2) * $redis->zAdd('z', 1, 'v1', 2, 'v2', 3, 'v3', 4, 'v4' ); // int(2)
* $redis->zRem('z', 'v2', 'v3'); // int(2) * $redis->zRem('z', 'v2', 'v3'); // int(2)
* $redis->zAdd('z', ['NX'], 5, 'v5'); // int(1) * $redis->zAdd('z', ['NX'], 5, 'v5'); // int(1)
* // ["v5"]=> float(5) * // ["v5"]=> float(5)
* // ["v6"]=> float(8) * // ["v6"]=> float(8)
* </pre> * </pre>
* </pre>
*/ */
public function zAdd($key, $options, $score1, $value1 = null, $score2 = null, $value2 = null, $scoreN = null, $valueN = null) public function zAdd($key, $options, $score1, $value1 = null, $score2 = null, $value2 = null, $scoreN = null, $valueN = null)
{ {
} }


/** /**
* @see zRem()
* @link https://redis.io/commands/zrem * @link https://redis.io/commands/zrem
* @deprecated use Redis::zRem()
* *
* @param string $key * @param string $key
* @param string|mixed $member1 * @param string|mixed $member1
* *
* @return int Number of deleted values * @return int Number of deleted values
*/ */
#[Deprecated(replacement: '%class%->zRem(%parametersList%)')]
public function zDelete($key, $member1, ...$otherMembers) public function zDelete($key, $member1, ...$otherMembers)
{ {
} }
* @param int $offset Optional argument if you wish to start somewhere other than the first element. * @param int $offset Optional argument if you wish to start somewhere other than the first element.
* @param int $limit Optional argument if you wish to limit the number of elements returned. * @param int $limit Optional argument if you wish to limit the number of elements returned.
* *
* @return array|bool Array containing the values in the specified range.
* @return array|false Array containing the values in the specified range.
* *
* @link https://redis.io/commands/zrangebylex * @link https://redis.io/commands/zrangebylex
* @example * @example
} }


/** /**
* @see zRemRangeByScore()
* @deprecated use Redis::zRemRangeByScore()
*
* @param string $key * @param string $key
* @param float $start * @param float $start
* @param float $end * @param float $end
*/ */
#[Deprecated(replacement: '%class%->zRemRangeByScore(%parametersList%)')]
public function zDeleteRangeByScore($key, $start, $end) public function zDeleteRangeByScore($key, $start, $end)
{ {
} }
} }


/** /**
* @see zRemRangeByRank()
* @link https://redis.io/commands/zremrangebyscore * @link https://redis.io/commands/zremrangebyscore
* @deprecated use Redis::zRemRangeByRank()
* *
* @param string $key * @param string $key
* @param int $start * @param int $start
* @param int $end * @param int $end
*/ */
#[Deprecated(replacement: '%class%->zRemRangeByRank(%parametersList%)')]
public function zDeleteRangeByRank($key, $start, $end) public function zDeleteRangeByRank($key, $start, $end)
{ {
} }
} }


/** /**
* @see zCard()
* @deprecated use Redis::zCard()
*
* @param string $key * @param string $key
* @return int * @return int
*/ */
#[Deprecated(replacement: '%class%->zCard(%parametersList%)')]
public function zSize($key) public function zSize($key)
{ {
} }
* @param string $key * @param string $key
* @param string|mixed $member * @param string|mixed $member
* *
* @return int|bool the item's score, or false if key or member is not exists
* @return int|false the item's score, or false if key or member is not exists
* *
* @link https://redis.io/commands/zrank * @link https://redis.io/commands/zrank
* @example * @example
* @param string $key * @param string $key
* @param string|mixed $member * @param string|mixed $member
* *
* @return int|bool the item's score, false - if key or member is not exists
* @return int|false the item's score, false - if key or member is not exists
* *
* @link https://redis.io/commands/zrevrank * @link https://redis.io/commands/zrevrank
*/ */
* *
* @param string $output * @param string $output
* @param array $zSetKeys * @param array $zSetKeys
* @param array $weights
* @param null|array $weights
* @param string $aggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on * @param string $aggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on
* duplicate entries during the zUnionStore * duplicate entries during the zUnionStore
* *
* $redis->zUnionStore('ko3', array('k1', 'k2'), array(5, 1)); // 4, 'ko3' => array('val0', 'val2', 'val3', 'val1') * $redis->zUnionStore('ko3', array('k1', 'k2'), array(5, 1)); // 4, 'ko3' => array('val0', 'val2', 'val3', 'val1')
* </pre> * </pre>
*/ */
public function zUnionStore($output, $zSetKeys, array $weights = null, $aggregateFunction = 'SUM')
public function zUnionStore($output, $zSetKeys, ?array $weights = null, $aggregateFunction = 'SUM')
{ {
} }


/** /**
* @see zUnionStore
* @deprecated use Redis::zUnionStore()
*
* @param string $Output * @param string $Output
* @param array $ZSetKeys * @param array $ZSetKeys
* @param array|null $Weights * @param array|null $Weights
* @param string $aggregateFunction * @param string $aggregateFunction
*/ */
#[Deprecated(replacement: '%class%->zUnionStore(%parametersList%)')]
public function zUnion($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') public function zUnion($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM')
{ {
} }
* *
* @param string $output * @param string $output
* @param array $zSetKeys * @param array $zSetKeys
* @param array $weights
* @param null|array $weights
* @param string $aggregateFunction Either "SUM", "MIN", or "MAX": * @param string $aggregateFunction Either "SUM", "MIN", or "MAX":
* defines the behaviour to use on duplicate entries during the zInterStore. * defines the behaviour to use on duplicate entries during the zInterStore.
* *
} }


/** /**
* @see zInterStore
* @deprecated use Redis::zInterStore()
*
* @param $Output * @param $Output
* @param $ZSetKeys * @param $ZSetKeys
* @param array|null $Weights * @param array|null $Weights
* @param string $aggregateFunction * @param string $aggregateFunction
*/ */
#[Deprecated(replacement: '%class%->zInterStore(%parametersList%)')]
public function zInter($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') public function zInter($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM')
{ {
} }
* Scan a sorted set for members, with optional pattern and count * Scan a sorted set for members, with optional pattern and count
* *
* @param string $key String, the set to scan. * @param string $key String, the set to scan.
* @param int $iterator Long (reference), initialized to NULL.
* @param int &$iterator Long (reference), initialized to NULL.
* @param string $pattern String (optional), the pattern to match. * @param string $pattern String (optional), the pattern to match.
* @param int $count How many keys to return per iteration (Redis might return a different number). * @param int $count How many keys to return per iteration (Redis might return a different number).
* *
* @return array|bool PHPRedis will return matching keys from Redis, or FALSE when iteration is complete
* @return array|false PHPRedis will return matching keys from Redis, or FALSE when iteration is complete
* *
* @link https://redis.io/commands/zscan * @link https://redis.io/commands/zscan
* @example * @example
* @param string $key * @param string $key
* @param string $hashKey * @param string $hashKey
* *
* @return string The value, if the command executed successfully BOOL FALSE in case of failure
* @return string|false The value, if the command executed successfully BOOL FALSE in case of failure
* *
* @link https://redis.io/commands/hget * @link https://redis.io/commands/hget
*/ */
* *
* @param string $key * @param string $key
* *
* @return int|bool the number of items in a hash, FALSE if the key doesn't exist or isn't a hash
* @return int|false the number of items in a hash, FALSE if the key doesn't exist or isn't a hash
* *
* @link https://redis.io/commands/hlen * @link https://redis.io/commands/hlen
* @example * @example
} }


/** /**
* Retirieve the values associated to the specified fields in the hash.
* Retrieve the values associated to the specified fields in the hash.
* *
* @param string $key * @param string $key
* @param array $hashKeys * @param array $hashKeys
* Scan a HASH value for members, with an optional pattern and count. * Scan a HASH value for members, with an optional pattern and count.
* *
* @param string $key * @param string $key
* @param int $iterator
* @param int &$iterator
* @param string $pattern Optional pattern to match against. * @param string $pattern Optional pattern to match against.
* @param int $count How many keys to return in a go (only a sugestion to Redis). * @param int $count How many keys to return in a go (only a sugestion to Redis).
* *
* @return int The number of elements added to the geospatial key * @return int The number of elements added to the geospatial key
* *
* @link https://redis.io/commands/geoadd * @link https://redis.io/commands/geoadd
* @since >=3.2
* @since >= 3.2
* *
* @example * @example
* <pre> * <pre>
* @return array One or more Redis Geohash encoded strings * @return array One or more Redis Geohash encoded strings
* *
* @link https://redis.io/commands/geohash * @link https://redis.io/commands/geohash
* @since >=3.2
* @since >= 3.2
* *
* @example * @example
* <pre> * <pre>
* @return array One or more longitude/latitude positions * @return array One or more longitude/latitude positions
* *
* @link https://redis.io/commands/geopos * @link https://redis.io/commands/geopos
* @since >=3.2
* @since >= 3.2
* *
* @example * @example
* <pre> * <pre>
* @return float The distance between the two passed members in the units requested (meters by default) * @return float The distance between the two passed members in the units requested (meters by default)
* *
* @link https://redis.io/commands/geodist * @link https://redis.io/commands/geodist
* @since >=3.2
* @since >= 3.2
* *
* @example * @example
* <pre> * <pre>
} }


/** /**
* @see eval()
* @deprecated use Redis::eval()
*
* @param string $script * @param string $script
* @param array $args * @param array $args
* @param int $numKeys * @param int $numKeys
* @return mixed @see eval() * @return mixed @see eval()
*/ */
#[Deprecated(replacement: '%class%->eval(%parametersList%)')]
public function evaluate($script, $args = array(), $numKeys = 0) public function evaluate($script, $args = array(), $numKeys = 0)
{ {
} }
} }


/** /**
* @see evalSha()
* @deprecated use Redis::evalSha()
*
* @param string $scriptSha * @param string $scriptSha
* @param array $args * @param array $args
* @param int $numKeys * @param int $numKeys
*/ */
#[Deprecated(replacement: '%class%->evalSha(%parametersList%)')]
public function evaluateSha($scriptSha, $args = array(), $numKeys = 0) public function evaluateSha($scriptSha, $args = array(), $numKeys = 0)
{ {
} }
* The data that comes out of DUMP is a binary representation of the key as Redis stores it. * The data that comes out of DUMP is a binary representation of the key as Redis stores it.
* @param string $key * @param string $key
* *
* @return string|bool The Redis encoded value of the key, or FALSE if the key doesn't exist
* @return string|false The Redis encoded value of the key, or FALSE if the key doesn't exist
* *
* @link https://redis.io/commands/dump * @link https://redis.io/commands/dump
* @example * @example
/** /**
* Scan the keyspace for keys * Scan the keyspace for keys
* *
* @param int $iterator Iterator, initialized to NULL.
* @param int &$iterator Iterator, initialized to NULL.
* @param string $pattern Pattern to match. * @param string $pattern Pattern to match.
* @param int $count Count of keys per iteration (only a suggestion to Redis). * @param int $count Count of keys per iteration (only a suggestion to Redis).
* *
* @return array|bool This function will return an array of keys or FALSE if there are no more keys.
* @return array|false This function will return an array of keys or FALSE if there are no more keys.
* *
* @link https://redis.io/commands/scan * @link https://redis.io/commands/scan
* @example * @example
* $redis->pfAdd('key2', array('elem3', 'elem2')); * $redis->pfAdd('key2', array('elem3', 'elem2'));
* $redis->pfCount('key1'); // int(2) * $redis->pfCount('key1'); // int(2)
* $redis->pfCount(array('key1', 'key2')); // int(3) * $redis->pfCount(array('key1', 'key2')); // int(3)
* </pre>
*/ */
public function pfCount($key) public function pfCount($key)
{ {
* $redis->pfAdd('key2', array('elem3', 'elem2')); * $redis->pfAdd('key2', array('elem3', 'elem2'));
* $redis->pfMerge('key3', array('key1', 'key2')); * $redis->pfMerge('key3', array('key1', 'key2'));
* $redis->pfCount('key3'); // int(3) * $redis->pfCount('key3'); // int(3)
* </pre>
*/ */
public function pfMerge($destKey, array $sourceKeys) public function pfMerge($destKey, array $sourceKeys)
{ {
/** /**
* Constructor * Constructor
* *
* @param string|array $hosts Name of the redis array from redis.ini or array of hosts to construct the array with
* @param array $opts Array of options
* @param string|string[] $hosts Name of the redis array from redis.ini or array of hosts to construct the array with
* @param null|array $opts Array of options
* *
* @link https://github.com/nicolasff/phpredis/blob/master/arrays.markdown * @link https://github.com/nicolasff/phpredis/blob/master/arrays.markdown
*/ */
public function __construct($hosts, array $opts = null)
public function __construct($hosts, ?array $opts = null)
{ {
} }


{ {
} }


/**
* @param string $host The host you want to retrieve the instance for
*
* @return Redis a redis instance connected to a specific node
*/
public function _instance($host)
{
}

/** /**
* Use this function when a new node is added and keys need to be rehashed. * Use this function when a new node is added and keys need to be rehashed.
*/ */

+ 35
- 23
build/stubs/redis_cluster.php View File

const SCAN_NORETRY = 0; const SCAN_NORETRY = 0;
const SCAN_RETRY = 1; const SCAN_RETRY = 1;


/**
* @since 5.3.0
*/
const SCAN_PREFIX = 2;

/**
* @since 5.3.0
*/
const SCAN_NOPREFIX = 3;

/** /**
* Serializers * Serializers
*/ */
/** /**
* Creates a Redis Cluster client * Creates a Redis Cluster client
* *
* @param string|null $name
* @param array $seeds
* @param float $timeout
* @param float $readTimeout
* @param bool $persistent
* @param string|null $auth
* @param string|null $name
* @param array $seeds
* @param float $timeout
* @param float $readTimeout
* @param bool $persistent
* @param string|string[]|null $auth
* @param array $connectionParameters extra config to send to redis
* @throws RedisClusterException * @throws RedisClusterException
* *
* @example * @example
* $redisClusterDev = new RedisCluster('test'); * $redisClusterDev = new RedisCluster('test');
* </pre> * </pre>
*/ */
public function __construct($name, $seeds, $timeout = null, $readTimeout = null, $persistent = false, $auth = null) { }
public function __construct($name, $seeds, $timeout = null, $readTimeout = null, $persistent = false, $auth = null, $connectionParameters = []) { }


/** /**
* Disconnects from the Redis instance, except when pconnect is used. * Disconnects from the Redis instance, except when pconnect is used.
public function hSetNx($key, $hashKey, $value) { } public function hSetNx($key, $hashKey, $value) { }


/** /**
* Retirieve the values associated to the specified fields in the hash.
* Retrieve the values associated to the specified fields in the hash.
* *
* @param string $key * @param string $key
* @param array $hashKeys * @param array $hashKeys
* $redisCluster->pfAdd('key2', array('elem3', 'elem2')); * $redisCluster->pfAdd('key2', array('elem3', 'elem2'));
* $redisCluster->pfCount('key1'); // int(2) * $redisCluster->pfCount('key1'); // int(2)
* $redisCluster->pfCount(array('key1', 'key2')); // int(3) * $redisCluster->pfCount(array('key1', 'key2')); // int(3)
* </pre>
*/ */
public function pfCount($key) { } public function pfCount($key) { }


* $redisCluster->pfAdd('key2', array('elem3', 'elem2')); * $redisCluster->pfAdd('key2', array('elem3', 'elem2'));
* $redisCluster->pfMerge('key3', array('key1', 'key2')); * $redisCluster->pfMerge('key3', array('key1', 'key2'));
* $redisCluster->pfCount('key3'); // int(3) * $redisCluster->pfCount('key3'); // int(3)
* </pre>
*/ */
public function pfMerge($destKey, array $sourceKeys) { } public function pfMerge($destKey, array $sourceKeys) { }


* *
* @param string $Output * @param string $Output
* @param array $ZSetKeys * @param array $ZSetKeys
* @param array $Weights
* @param null|array $Weights
* @param string $aggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on * @param string $aggregateFunction Either "SUM", "MIN", or "MAX": defines the behaviour to use on
* duplicate entries during the zUnion. * duplicate entries during the zUnion.
* *
* $redisCluster->zUnionStore('ko3', array('k1', 'k2'), array(5, 1)); // 4, 'ko3' => array('val0', 'val2', 'val3','val1') * $redisCluster->zUnionStore('ko3', array('k1', 'k2'), array(5, 1)); // 4, 'ko3' => array('val0', 'val2', 'val3','val1')
* </pre> * </pre>
*/ */
public function zUnionStore($Output, $ZSetKeys, array $Weights = null, $aggregateFunction = 'SUM') { }
public function zUnionStore($Output, $ZSetKeys, ?array $Weights = null, $aggregateFunction = 'SUM') { }


/** /**
* Intersect multiple sorted sets and store the resulting sorted set in a new key * Intersect multiple sorted sets and store the resulting sorted set in a new key
* *
* @param string $Output * @param string $Output
* @param array $ZSetKeys * @param array $ZSetKeys
* @param array $Weights
* @param null|array $Weights
* @param string $aggregateFunction Either "SUM", "MIN", or "MAX": * @param string $aggregateFunction Either "SUM", "MIN", or "MAX":
* defines the behaviour to use on duplicate entries during the zInterStore. * defines the behaviour to use on duplicate entries during the zInterStore.
* *
* Scan a set for members. * Scan a set for members.
* *
* @param string $key The set to search. * @param string $key The set to search.
* @param int $iterator LONG (reference) to the iterator as we go.
* @param int &$iterator LONG (reference) to the iterator as we go.
* @param null $pattern String, optional pattern to match against. * @param null $pattern String, optional pattern to match against.
* @param int $count How many members to return at a time (Redis might return a different amount). * @param int $count How many members to return at a time (Redis might return a different amount).
* *
* Scan a sorted set for members, with optional pattern and count. * Scan a sorted set for members, with optional pattern and count.
* *
* @param string $key String, the set to scan. * @param string $key String, the set to scan.
* @param int $iterator Long (reference), initialized to NULL.
* @param int &$iterator Long (reference), initialized to NULL.
* @param string $pattern String (optional), the pattern to match. * @param string $pattern String (optional), the pattern to match.
* @param int $count How many keys to return per iteration (Redis might return a different number). * @param int $count How many keys to return per iteration (Redis might return a different number).
* *
* Scan a HASH value for members, with an optional pattern and count. * Scan a HASH value for members, with an optional pattern and count.
* *
* @param string $key * @param string $key
* @param int $iterator
* @param int &$iterator
* @param string $pattern Optional pattern to match against. * @param string $pattern Optional pattern to match against.
* @param int $count How many keys to return in a go (only a sugestion to Redis). * @param int $count How many keys to return in a go (only a sugestion to Redis).
* *
/** /**
* Returns members of a geospatial index as standard geohash strings * Returns members of a geospatial index as standard geohash strings
* *
* @param $key string
* @param $member1 string
* @param $member2 string
* @param $memberN string
* @param string $key
* @param string $member1
* @param string $member2
* @param string $memberN
* *
* @example * @example
* <pre> * <pre>
/** /**
* Returns longitude and latitude of members of a geospatial index * Returns longitude and latitude of members of a geospatial index
* *
* @param $key string
* @param $member1 string
* @param $member2 string
* @param $memberN string
*
* @param string $key
* @param string $member1
* @param string $member2
* @param string $memberN
* @example * @example
* <pre> * <pre>
* $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1) * $redisCluster->geoAdd('Sicily', 15.087269, 37.502669, "Catania"); // int(1)

+ 20
- 0
config/config.sample.php View File

* For enhanced security it is recommended to configure Redis * For enhanced security it is recommended to configure Redis
* to require a password. See http://redis.io/topics/security * to require a password. See http://redis.io/topics/security
* for more information. * for more information.
*
* We also support redis SSL/TLS encryption as of version 6.
* See https://redis.io/topics/encryption for more information.
*/ */
'redis' => [ 'redis' => [
'host' => 'localhost', // can also be a unix domain socket: '/tmp/redis.sock' 'host' => 'localhost', // can also be a unix domain socket: '/tmp/redis.sock'
'port' => 6379, 'port' => 6379,
'timeout' => 0.0, 'timeout' => 0.0,
'read_timeout' => 0.0,
'user' => '', // Optional, if not defined no password will be used.
'password' => '', // Optional, if not defined no password will be used. 'password' => '', // Optional, if not defined no password will be used.
'dbindex' => 0, // Optional, if undefined SELECT will not run and will use Redis Server's default DB Index. 'dbindex' => 0, // Optional, if undefined SELECT will not run and will use Redis Server's default DB Index.
// If redis is encrypted, provide certificates
// SSL context https://www.php.net/manual/en/context.ssl.php
'ssl_context' => [
'local_cert' => '/certs/redis.crt',
'local_pk' => '/certs/redis.key',
'cafile' => '/certs/ca.crt'
]
], ],


/** /**
'timeout' => 0.0, 'timeout' => 0.0,
'read_timeout' => 0.0, 'read_timeout' => 0.0,
'failover_mode' => \RedisCluster::FAILOVER_ERROR, 'failover_mode' => \RedisCluster::FAILOVER_ERROR,
'user' => '', // Optional, if not defined no password will be used.
'password' => '', // Optional, if not defined no password will be used. 'password' => '', // Optional, if not defined no password will be used.
// If redis is encrypted, provide certificates
// SSL context https://www.php.net/manual/en/context.ssl.php
'ssl_context' => [
'local_cert' => '/certs/redis.crt',
'local_pk' => '/certs/redis.key',
'cafile' => '/certs/ca.crt'
]
], ],





+ 84
- 22
lib/private/RedisFactory.php View File

namespace OC; namespace OC;


class RedisFactory { class RedisFactory {
/** @var \Redis */
public const REDIS_MINIMAL_VERSION = '2.2.5';
public const REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION = '5.3.0';

/** @var \Redis|\RedisCluster */
private $instance; private $instance;


/** @var SystemConfig */ /** @var SystemConfig */
} }


private function create() { private function create() {
if ($config = $this->config->getValue('redis.cluster', [])) {
$isCluster = !empty($this->config->getValue('redis.cluster', []));
$config = $this->config->getValue('redis', []);

// Init cluster config if any
if ($isCluster) {
if (!class_exists('RedisCluster')) { if (!class_exists('RedisCluster')) {
throw new \Exception('Redis Cluster support is not available'); throw new \Exception('Redis Cluster support is not available');
} }
// cluster config
if (isset($config['timeout'])) {
$timeout = $config['timeout'];
} else {
$timeout = null;
}
if (isset($config['read_timeout'])) {
$readTimeout = $config['read_timeout'];
// Replace config with the cluster config
$config = $this->config->getValue('redis.cluster', []);
}

if (isset($config['timeout'])) {
$timeout = $config['timeout'];
} else {
$timeout = null;
}

if (isset($config['read_timeout'])) {
$readTimeout = $config['read_timeout'];
} else {
$readTimeout = null;
}

$auth = null;
if (isset($config['password']) && $config['password'] !== '') {
if (isset($config['user']) && $config['user'] !== '') {
$auth = [$config['user'], $config['password']];
} else { } else {
$readTimeout = null;
$auth = $config['password'];
} }
if (isset($config['password']) && $config['password'] !== '') {
$this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $config['password']);
}

// # TLS support
// # https://github.com/phpredis/phpredis/issues/1600
$connectionParameters = $this->getSslContext($config);

// cluster config
if ($isCluster) {
if ($connectionParameters !== null) {
$this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, false, $auth, $connectionParameters);
} else { } else {
$this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout);
$this->instance = new \RedisCluster(null, $config['seeds'], $timeout, $readTimeout, $auth);
} }


if (isset($config['failover_mode'])) { if (isset($config['failover_mode'])) {
} }
} else { } else {
$this->instance = new \Redis(); $this->instance = new \Redis();
$config = $this->config->getValue('redis', []);
if (isset($config['host'])) { if (isset($config['host'])) {
$host = $config['host']; $host = $config['host'];
} else { } else {
$host = '127.0.0.1'; $host = '127.0.0.1';
} }

if (isset($config['port'])) { if (isset($config['port'])) {
$port = $config['port']; $port = $config['port'];
} elseif ($host[0] !== '/') { } elseif ($host[0] !== '/') {
} else { } else {
$port = null; $port = null;
} }
if (isset($config['timeout'])) {
$timeout = $config['timeout'];
} else {
$timeout = 0.0; // unlimited

if (!empty($connectionParameters)) {
$connectionParameters = [
'stream' => $this->getSslContext($config)
];
} }


$this->instance->connect($host, $port, $timeout);
if (isset($config['password']) && $config['password'] !== '') {
$this->instance->auth($config['password']);
$this->instance->connect($host, $port, $timeout, null, 0, $readTimeout, $connectionParameters);

// Auth if configured
if ($auth !== null) {
$this->instance->auth($auth);
} }


if (isset($config['dbindex'])) { if (isset($config['dbindex'])) {
} }
} }


/**
* Get the ssl context config
*
* @param Array $config the current config
* @return Array
* @throws \UnexpectedValueException
*/
private function getSslContext($config) {
if (isset($config['ssl_context'])) {
if (!$this->isConnectionParametersSupported()) {
throw new \UnexpectedValueException(\sprintf(
'php-redis extension must be version %s or higher to support ssl context',
self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION
));
}
return $config['ssl_context'];
}
return [];
}

public function getInstance() { public function getInstance() {
if (!$this->isAvailable()) { if (!$this->isAvailable()) {
throw new \Exception('Redis support is not available'); throw new \Exception('Redis support is not available');
return extension_loaded('redis') return extension_loaded('redis')
&& version_compare(phpversion('redis'), '2.2.5', '>='); && version_compare(phpversion('redis'), '2.2.5', '>=');
} }

/**
* Php redis does support configurable extra parameters since version 5.3.0, see: https://github.com/phpredis/phpredis#connect-open.
* We need to check if the current version supports extra connection parameters, otherwise the connect method will throw an exception
*
* @return boolean
*/
private function isConnectionParametersSupported(): bool {
return \extension_loaded('redis') &&
\version_compare(\phpversion('redis'), self::REDIS_EXTRA_PARAMETERS_MINIMAL_VERSION, '>=');
}
} }

Loading…
Cancel
Save