1<?php 2 3/* 4 * This file is part of the Predis package. 5 * 6 * (c) Daniele Alessandri <suppakilla@gmail.com> 7 * 8 * For the full copyright and license information, please view the LICENSE 9 * file that was distributed with this source code. 10 */ 11 12namespace Predis\Connection; 13 14use Predis\Command\RawCommand; 15 16/** 17 * Standard connection factory for creating connections to Redis nodes. 18 * 19 * @author Daniele Alessandri <suppakilla@gmail.com> 20 */ 21class Factory implements FactoryInterface 22{ 23 protected $schemes = array( 24 'tcp' => 'Predis\Connection\StreamConnection', 25 'unix' => 'Predis\Connection\StreamConnection', 26 'redis' => 'Predis\Connection\StreamConnection', 27 'http' => 'Predis\Connection\WebdisConnection', 28 ); 29 30 /** 31 * Checks if the provided argument represents a valid connection class 32 * implementing Predis\Connection\NodeConnectionInterface. Optionally, 33 * callable objects are used for lazy initialization of connection objects. 34 * 35 * @param mixed $initializer FQN of a connection class or a callable for lazy initialization. 36 * 37 * @throws \InvalidArgumentException 38 * 39 * @return mixed 40 */ 41 protected function checkInitializer($initializer) 42 { 43 if (is_callable($initializer)) { 44 return $initializer; 45 } 46 47 $class = new \ReflectionClass($initializer); 48 49 if (!$class->isSubclassOf('Predis\Connection\NodeConnectionInterface')) { 50 throw new \InvalidArgumentException( 51 'A connection initializer must be a valid connection class or a callable object.' 52 ); 53 } 54 55 return $initializer; 56 } 57 58 /** 59 * {@inheritdoc} 60 */ 61 public function define($scheme, $initializer) 62 { 63 $this->schemes[$scheme] = $this->checkInitializer($initializer); 64 } 65 66 /** 67 * {@inheritdoc} 68 */ 69 public function undefine($scheme) 70 { 71 unset($this->schemes[$scheme]); 72 } 73 74 /** 75 * {@inheritdoc} 76 */ 77 public function create($parameters) 78 { 79 if (!$parameters instanceof ParametersInterface) { 80 $parameters = $this->createParameters($parameters); 81 } 82 83 $scheme = $parameters->scheme; 84 85 if (!isset($this->schemes[$scheme])) { 86 throw new \InvalidArgumentException("Unknown connection scheme: '$scheme'."); 87 } 88 89 $initializer = $this->schemes[$scheme]; 90 91 if (is_callable($initializer)) { 92 $connection = call_user_func($initializer, $parameters, $this); 93 } else { 94 $connection = new $initializer($parameters); 95 $this->prepareConnection($connection); 96 } 97 98 if (!$connection instanceof NodeConnectionInterface) { 99 throw new \UnexpectedValueException( 100 'Objects returned by connection initializers must implement '. 101 "'Predis\Connection\NodeConnectionInterface'." 102 ); 103 } 104 105 return $connection; 106 } 107 108 /** 109 * {@inheritdoc} 110 */ 111 public function aggregate(AggregateConnectionInterface $connection, array $parameters) 112 { 113 foreach ($parameters as $node) { 114 $connection->add($node instanceof NodeConnectionInterface ? $node : $this->create($node)); 115 } 116 } 117 118 /** 119 * Creates a connection parameters instance from the supplied argument. 120 * 121 * @param mixed $parameters Original connection parameters. 122 * 123 * @return ParametersInterface 124 */ 125 protected function createParameters($parameters) 126 { 127 return Parameters::create($parameters); 128 } 129 130 /** 131 * Prepares a connection instance after its initialization. 132 * 133 * @param NodeConnectionInterface $connection Connection instance. 134 */ 135 protected function prepareConnection(NodeConnectionInterface $connection) 136 { 137 $parameters = $connection->getParameters(); 138 139 if (isset($parameters->password)) { 140 $connection->addConnectCommand( 141 new RawCommand(array('AUTH', $parameters->password)) 142 ); 143 } 144 145 if (isset($parameters->database)) { 146 $connection->addConnectCommand( 147 new RawCommand(array('SELECT', $parameters->database)) 148 ); 149 } 150 } 151} 152