File: /var/www/html/wp-content/plugins/includes/class-predis.php
<?php
/**
* Predis client class.
*
* @package Rhubarb\RedisCache
*/
namespace Rhubarb\RedisCache;
use Exception;
defined( '\\ABSPATH' ) || exit;
class Predis {
/**
* The Redis client.
*
* @var mixed
*/
protected $redis;
/**
* Connect to Redis.
*
* @param int|null $read_timeout The read timeout in seconds.
* @return void
*/
public function connect( $read_timeout = null ) {
if ( ! function_exists( 'stream_socket_client' ) ) {
return;
}
// Load bundled Predis library.
if ( ! class_exists( '\Predis\Client' ) ) {
require_once WP_REDIS_PLUGIN_PATH . '/dependencies/predis/predis/autoload.php';
}
$servers = false;
$options = [];
$parameters = [
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
'timeout' => 1,
'read_timeout' => $read_timeout ?? 1,
];
$settings = [
'scheme',
'host',
'port',
'path',
'password',
'database',
'timeout',
'read_timeout',
];
foreach ( $settings as $setting ) {
$constant = sprintf( 'WP_REDIS_%s', strtoupper( $setting ) );
if ( defined( $constant ) ) {
$parameters[ $setting ] = constant( $constant );
}
}
if ( isset( $parameters['password'] ) && $parameters['password'] === '' ) {
unset( $parameters['password'] );
}
if ( defined( 'WP_REDIS_SHARDS' ) ) {
$servers = WP_REDIS_SHARDS;
$parameters['shards'] = $servers;
} elseif ( defined( 'WP_REDIS_SENTINEL' ) ) {
$servers = WP_REDIS_SERVERS;
$parameters['servers'] = $servers;
$options['replication'] = 'sentinel';
$options['service'] = WP_REDIS_SENTINEL;
} elseif ( defined( 'WP_REDIS_SERVERS' ) ) {
$servers = WP_REDIS_SERVERS;
$parameters['servers'] = $servers;
$options['replication'] = 'predis';
} elseif ( defined( 'WP_REDIS_CLUSTER' ) ) {
$servers = $this->build_cluster_connection_array();
$parameters['cluster'] = $servers;
$options['cluster'] = 'redis';
}
if ( strcasecmp( 'unix', $parameters['scheme'] ) === 0 ) {
unset( $parameters['host'], $parameters['port'] );
}
if ( isset( $parameters['read_timeout'] ) && $parameters['read_timeout'] ) {
$parameters['read_write_timeout'] = $parameters['read_timeout'];
}
foreach ( [ 'WP_REDIS_SERVERS', 'WP_REDIS_SHARDS', 'WP_REDIS_CLUSTER' ] as $constant ) {
if ( defined( $constant ) ) {
if ( $parameters['database'] ) {
$options['parameters']['database'] = $parameters['database'];
}
if ( isset( $parameters['password'] ) ) {
if ( is_array( $parameters['password'] ) ) {
$options['parameters']['username'] = WP_REDIS_PASSWORD[0];
$options['parameters']['password'] = WP_REDIS_PASSWORD[1];
} else {
$options['parameters']['password'] = WP_REDIS_PASSWORD;
}
}
}
}
if ( isset( $parameters['password'] ) ) {
if ( is_array( $parameters['password'] ) ) {
$parameters['username'] = array_shift( $parameters['password'] );
$parameters['password'] = implode( '', $parameters['password'] );
}
if ( defined( 'WP_REDIS_USERNAME' ) ) {
$parameters['username'] = WP_REDIS_USERNAME;
}
}
if ( defined( 'WP_REDIS_SSL_CONTEXT' ) && ! empty( WP_REDIS_SSL_CONTEXT ) ) {
$parameters['ssl'] = WP_REDIS_SSL_CONTEXT;
}
$this->redis = new \Predis\Client( $servers ?: $parameters, $options );
$this->redis->connect();
}
/**
* Flushes the entire Redis database using the `WP_REDIS_FLUSH_TIMEOUT`.
*
* @param bool $throw_exception Whether to throw exception on error.
* @return bool
*/
public function flush( $throw_exception = false ) {
if ( is_null( $this->redis ) ) {
$flush_timeout = defined( 'WP_REDIS_FLUSH_TIMEOUT' )
? intval( WP_REDIS_FLUSH_TIMEOUT )
: 5;
try {
$this->connect( $flush_timeout );
} catch ( Exception $exception ) {
if ( $throw_exception ) {
throw $exception;
}
return false;
}
if ( is_null( $this->redis ) ) {
return false;
}
}
if ( defined( 'WP_REDIS_CLUSTER' ) ) {
try {
foreach ( $this->redis->getIterator() as $master ) {
$master->flushdb();
}
} catch ( Exception $exception ) {
if ( $throw_exception ) {
throw $exception;
}
return false;
}
return true;
}
try {
$this->redis->flushdb();
} catch ( Exception $exception ) {
if ( $throw_exception ) {
throw $exception;
}
return false;
}
return true;
}
/**
* Flushes the entire Redis database using the `WP_REDIS_FLUSH_TIMEOUT`
* and will throw an exception if anything goes wrong.
*
* @return bool
*/
public function flushOrFail() {
return $this->flush( true );
}
/**
* Builds a clean connection array out of redis clusters array.
*
* @return array
*/
protected function build_cluster_connection_array() {
$cluster = array_values( WP_REDIS_CLUSTER );
foreach ( $cluster as $key => $server ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url
$components = parse_url( $server );
if ( ! empty( $components['scheme'] ) ) {
$scheme = $components['scheme'];
} elseif ( defined( 'WP_REDIS_SCHEME' ) ) {
$scheme = WP_REDIS_SCHEME;
} else {
$scheme = null;
}
if ( isset( $scheme ) ) {
$cluster[ $key ] = sprintf(
'%s://%s:%d',
$scheme,
$components['host'],
$components['port']
);
} else {
$cluster[ $key ] = sprintf(
'%s:%d',
$components['host'],
$components['port']
);
}
}
return $cluster;
}
}