123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- <?php
- namespace Drupal\redis;
- use Drupal\Core\Site\Settings;
- /**
- * Common code and client singleton, for all Redis clients.
- */
- class ClientFactory {
- /**
- * Redis default host.
- */
- const REDIS_DEFAULT_HOST = "127.0.0.1";
- /**
- * Redis default port.
- */
- const REDIS_DEFAULT_PORT = 6379;
- /**
- * Redis default database: will select none (Database 0).
- */
- const REDIS_DEFAULT_BASE = NULL;
- /**
- * Redis default password: will not authenticate.
- */
- const REDIS_DEFAULT_PASSWORD = NULL;
- /**
- * Cache implementation namespace.
- */
- const REDIS_IMPL_CACHE = '\\Drupal\\redis\\Cache\\';
- /**
- * Lock implementation namespace.
- */
- const REDIS_IMPL_LOCK = '\\Drupal\\redis\\Lock\\';
- /**
- * Lock implementation namespace.
- */
- const REDIS_IMPL_FLOOD = '\\Drupal\\redis\\Flood\\';
- /**
- * Persistent Lock implementation namespace.
- */
- const REDIS_IMPL_PERSISTENT_LOCK = '\\Drupal\\redis\\PersistentLock\\';
- /**
- * Client implementation namespace.
- */
- const REDIS_IMPL_CLIENT = '\\Drupal\\redis\\Client\\';
- /**
- * Queue implementation namespace.
- */
- const REDIS_IMPL_QUEUE = '\\Drupal\\redis\\Queue\\';
- /**
- * Reliable queue implementation namespace.
- */
- const REDIS_IMPL_RELIABLE_QUEUE = '\\Drupal\\redis\\Queue\\Reliable';
- /**
- * @var \Drupal\redis\ClientInterface
- */
- protected static $_clientInterface;
- /**
- * @var mixed
- */
- protected static $_client;
- public static function hasClient() {
- return isset(self::$_client);
- }
- /**
- * Set client proxy.
- */
- public static function setClient(ClientInterface $interface) {
- if (isset(self::$_client)) {
- throw new \Exception("Once Redis client is connected, you cannot change client proxy instance.");
- }
- self::$_clientInterface = $interface;
- }
- /**
- * Lazy instanciate client proxy depending on the actual configuration.
- *
- * If you are using a lock or cache backend using one of the Redis client
- * implementations, this will be overridden at early bootstrap phase and
- * configuration will be ignored.
- *
- * @return ClientInterface
- */
- public static function getClientInterface()
- {
- if (!isset(self::$_clientInterface))
- {
- $settings = Settings::get('redis.connection', []);
- if (!empty($settings['interface']))
- {
- $className = self::getClass(self::REDIS_IMPL_CLIENT, $settings['interface']);
- self::$_clientInterface = new $className();
- }
- elseif (class_exists('Predis\Client'))
- {
- // Transparent and abitrary preference for Predis library.
- $className = self::getClass(self::REDIS_IMPL_CLIENT, 'Predis');
- self::$_clientInterface = new $className();
- }
- elseif (class_exists('Redis'))
- {
- // Fallback on PhpRedis if available.
- $className = self::getClass(self::REDIS_IMPL_CLIENT, 'PhpRedis');
- self::$_clientInterface = new $className();
- }
- else
- {
- if (!isset(self::$_clientInterface))
- {
- throw new \Exception("No client interface set.");
- }
- }
- }
- return self::$_clientInterface;
- }
- /**
- * Get underlaying library name.
- *
- * @return string
- */
- public static function getClientName() {
- return self::getClientInterface()->getName();
- }
- /**
- * Get client singleton.
- */
- public static function getClient() {
- if (!isset(self::$_client)) {
- $settings = Settings::get('redis.connection', []);
- $settings += [
- 'host' => self::REDIS_DEFAULT_HOST,
- 'port' => self::REDIS_DEFAULT_PORT,
- 'base' => self::REDIS_DEFAULT_BASE,
- 'password' => self::REDIS_DEFAULT_PASSWORD,
- ];
- // If using replication, lets create the client appropriately.
- if (isset($settings['replication']) && $settings['replication'] === TRUE) {
- foreach ($settings['replication.host'] as $key => $replicationHost) {
- if (!isset($replicationHost['port'])) {
- $settings['replication.host'][$key]['port'] = self::REDIS_DEFAULT_PORT;
- }
- }
- self::$_client = self::getClientInterface()->getClient(
- $settings['host'],
- $settings['port'],
- $settings['base'],
- $settings['password'],
- $settings['replication.host']);
- }
- else {
- self::$_client = self::getClientInterface()->getClient(
- $settings['host'],
- $settings['port'],
- $settings['base'],
- $settings['password']);
- }
- }
- return self::$_client;
- }
- /**
- * Get specific class implementing the current client usage for the specific
- * asked core subsystem.
- *
- * @param string $system
- * One of the ClientFactory::IMPL_* constant.
- * @param string $clientName
- * Client name, if fixed.
- *
- * @return string
- * Class name, if found.
- *
- * @throws \Exception
- * If not found.
- */
- public static function getClass($system, $clientName = NULL) {
- $className = $system . ($clientName ?: self::getClientName());
- if (!class_exists($className)) {
- throw new \Exception($className . " does not exists");
- }
- return $className;
- }
- /**
- * For unit testing only reset internals.
- */
- static public function reset() {
- self::$_clientInterface = null;
- self::$_client = null;
- }
- }
|