Эх сурвалжийг харах

Specify the server profile in constructor of the connection factory.

When no server profile is specified, the connection factory will not push
any initialization command to the newly created connection object.

This change is mainly useful when using redis-cluster and also makes it
possible to easily inject commands such as "SCRIPT LOAD" at initialization
time by grouping everything into one common place simply by extending the
connection factory class.
Daniele Alessandri 13 жил өмнө
parent
commit
8567b05459

+ 2 - 2
lib/Predis/Client.php

@@ -97,10 +97,10 @@ class Client implements ClientInterface
             $replication = isset($this->options->replication) && $this->options->replication;
             $replication = isset($this->options->replication) && $this->options->replication;
             $connection = $this->options->{$replication ? 'replication' : 'cluster'};
             $connection = $this->options->{$replication ? 'replication' : 'cluster'};
 
 
-            return $this->connections->createAggregated($connection, $parameters, $this->profile);
+            return $this->connections->createAggregated($connection, $parameters);
         }
         }
 
 
-        return $this->connections->create($parameters, $this->profile);
+        return $this->connections->create($parameters);
     }
     }
 
 
     /**
     /**

+ 46 - 23
lib/Predis/Connection/ConnectionFactory.php

@@ -22,14 +22,18 @@ use Predis\Profile\ServerProfileInterface;
  */
  */
 class ConnectionFactory implements ConnectionFactoryInterface
 class ConnectionFactory implements ConnectionFactoryInterface
 {
 {
-    private $schemes;
+    protected $schemes;
+    protected $profile;
 
 
     /**
     /**
      * Initializes a new instance of the default connection factory class used by Predis.
      * Initializes a new instance of the default connection factory class used by Predis.
+     *
+     * @param ServerProfileInterface $profile Server profile used to initialize new connections.
      */
      */
-    public function __construct()
+    public function __construct(ServerProfileInterface $profile = null)
     {
     {
         $this->schemes = $this->getDefaultSchemes();
         $this->schemes = $this->getDefaultSchemes();
+        $this->profile = $profile;
     }
     }
 
 
     /**
     /**
@@ -40,7 +44,7 @@ class ConnectionFactory implements ConnectionFactoryInterface
     protected function getDefaultSchemes()
     protected function getDefaultSchemes()
     {
     {
         return array(
         return array(
-            'tcp' => 'Predis\Connection\StreamConnection',
+            'tcp'  => 'Predis\Connection\StreamConnection',
             'unix' => 'Predis\Connection\StreamConnection',
             'unix' => 'Predis\Connection\StreamConnection',
             'http' => 'Predis\Connection\WebdisConnection',
             'http' => 'Predis\Connection\WebdisConnection',
         );
         );
@@ -90,7 +94,7 @@ class ConnectionFactory implements ConnectionFactoryInterface
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function create($parameters, ServerProfileInterface $profile = null)
+    public function create($parameters)
     {
     {
         if (!$parameters instanceof ConnectionParametersInterface) {
         if (!$parameters instanceof ConnectionParametersInterface) {
             $parameters = new ConnectionParameters($parameters ?: array());
             $parameters = new ConnectionParameters($parameters ?: array());
@@ -104,15 +108,13 @@ class ConnectionFactory implements ConnectionFactoryInterface
 
 
         $initializer = $this->schemes[$scheme];
         $initializer = $this->schemes[$scheme];
 
 
-        if (!is_callable($initializer)) {
+        if (is_callable($initializer)) {
+            $connection = call_user_func($initializer, $parameters, $this);
+        } else {
             $connection = new $initializer($parameters);
             $connection = new $initializer($parameters);
-            $this->prepareConnection($connection, $profile ?: ServerProfile::getDefault());
-
-            return $connection;
+            $this->prepareConnection($connection);
         }
         }
 
 
-        $connection = call_user_func($initializer, $parameters, $profile);
-
         if (!$connection instanceof SingleConnectionInterface) {
         if (!$connection instanceof SingleConnectionInterface) {
             throw new \InvalidArgumentException(
             throw new \InvalidArgumentException(
                 'Objects returned by connection initializers must implement ' .
                 'Objects returned by connection initializers must implement ' .
@@ -126,10 +128,10 @@ class ConnectionFactory implements ConnectionFactoryInterface
     /**
     /**
      * {@inheritdoc}
      * {@inheritdoc}
      */
      */
-    public function createAggregated(AggregatedConnectionInterface $connection, $parameters, ServerProfileInterface $profile = null)
+    public function createAggregated(AggregatedConnectionInterface $connection, Array $parameters)
     {
     {
         foreach ($parameters as $node) {
         foreach ($parameters as $node) {
-            $connection->add($node instanceof SingleConnectionInterface ? $node : $this->create($node, $profile));
+            $connection->add($node instanceof SingleConnectionInterface ? $node : $this->create($node));
         }
         }
 
 
         return $connection;
         return $connection;
@@ -139,20 +141,41 @@ class ConnectionFactory implements ConnectionFactoryInterface
      * Prepares a connection object after its initialization.
      * Prepares a connection object after its initialization.
      *
      *
      * @param SingleConnectionInterface $connection Instance of a connection object.
      * @param SingleConnectionInterface $connection Instance of a connection object.
-     * @param ServerProfileInterface $profile $connection Instance of a connection object.
      */
      */
-    protected function prepareConnection(SingleConnectionInterface $connection, ServerProfileInterface $profile)
+    protected function prepareConnection(SingleConnectionInterface $connection)
     {
     {
-        $parameters = $connection->getParameters();
-
-        if (isset($parameters->password)) {
-            $command = $profile->createCommand('auth', array($parameters->password));
-            $connection->pushInitCommand($command);
+        if (isset($this->profile)) {
+            $parameters = $connection->getParameters();
+
+            if (isset($parameters->password)) {
+                $command = $this->profile->createCommand('auth', array($parameters->password));
+                $connection->pushInitCommand($command);
+            }
+
+            if (isset($parameters->database)) {
+                $command = $this->profile->createCommand('select', array($parameters->database));
+                $connection->pushInitCommand($command);
+            }
         }
         }
+    }
 
 
-        if (isset($parameters->database)) {
-            $command = $profile->createCommand('select', array($parameters->database));
-            $connection->pushInitCommand($command);
-        }
+    /**
+     * Sets the server profile used to create initialization commands for connections.
+     *
+     * @param ServerProfileInterface $profile Server profile instance.
+     */
+    public function setProfile(ServerProfileInterface $profile)
+    {
+        $this->profile = $profile;
+    }
+
+    /**
+     * Returns the server profile used to create initialization commands for connections.
+     *
+     * @return ServerProfileInterface
+     */
+    public function getProfile()
+    {
+        return $this->profile;
     }
     }
 }
 }

+ 2 - 2
lib/Predis/Connection/ConnectionFactoryInterface.php

@@ -42,7 +42,7 @@ interface ConnectionFactoryInterface
      * @param mixed $parameters Parameters for the connection.
      * @param mixed $parameters Parameters for the connection.
      * @return Predis\Connection\SingleConnectionInterface
      * @return Predis\Connection\SingleConnectionInterface
      */
      */
-    public function create($parameters, ServerProfileInterface $profile = null);
+    public function create($parameters);
 
 
     /**
     /**
      * Prepares an aggregation of connection objects.
      * Prepares an aggregation of connection objects.
@@ -51,5 +51,5 @@ interface ConnectionFactoryInterface
      * @param array $parameters List of parameters for each connection object.
      * @param array $parameters List of parameters for each connection object.
      * @return Predis\Connection\AggregatedConnectionInterface
      * @return Predis\Connection\AggregatedConnectionInterface
      */
      */
-    public function createAggregated(AggregatedConnectionInterface $cluster, $parameters, ServerProfileInterface $profile = null);
+    public function createAggregated(AggregatedConnectionInterface $cluster, Array $parameters);
 }
 }

+ 1 - 0
lib/Predis/Connection/ConnectionParameters.php

@@ -11,6 +11,7 @@
 
 
 namespace Predis\Connection;
 namespace Predis\Connection;
 
 
+use Predis\ClientException;
 use Predis\Option\OptionInterface;
 use Predis\Option\OptionInterface;
 
 
 /**
 /**

+ 3 - 1
lib/Predis/Option/ClientConnectionFactory.php

@@ -29,6 +29,7 @@ class ClientConnectionFactory extends AbstractOption
         if ($value instanceof ConnectionFactoryInterface) {
         if ($value instanceof ConnectionFactoryInterface) {
             return $value;
             return $value;
         }
         }
+
         if (is_array($value)) {
         if (is_array($value)) {
             $factory = $this->getDefault($options);
             $factory = $this->getDefault($options);
 
 
@@ -38,6 +39,7 @@ class ClientConnectionFactory extends AbstractOption
 
 
             return $factory;
             return $factory;
         }
         }
+
         if (is_string($value) && class_exists($value)) {
         if (is_string($value) && class_exists($value)) {
             if (!($factory = new $value()) && !$factory instanceof ConnectionFactoryInterface) {
             if (!($factory = new $value()) && !$factory instanceof ConnectionFactoryInterface) {
                 throw new \InvalidArgumentException("Class $value must be an instance of Predis\Connection\ConnectionFactoryInterface");
                 throw new \InvalidArgumentException("Class $value must be an instance of Predis\Connection\ConnectionFactoryInterface");
@@ -54,6 +56,6 @@ class ClientConnectionFactory extends AbstractOption
      */
      */
     public function getDefault(ClientOptionsInterface $options)
     public function getDefault(ClientOptionsInterface $options)
     {
     {
-        return new ConnectionFactory();
+        return new ConnectionFactory($options->profile);
     }
     }
 }
 }

+ 32 - 9
tests/Predis/Connection/ConnectionFactoryTest.php

@@ -116,9 +116,9 @@ class ConnectionFactoryTest extends StandardTestCase
         $profile = $this->getMock('Predis\Profile\ServerProfileInterface');
         $profile = $this->getMock('Predis\Profile\ServerProfileInterface');
         $profile->expects($this->never())->method('create');
         $profile->expects($this->never())->method('create');
 
 
-        $factory = new ConnectionFactory();
+        $factory = new ConnectionFactory($profile);
         $parameters = new ConnectionParameters();
         $parameters = new ConnectionParameters();
-        $connection = $factory->create($parameters, $profile);
+        $connection = $factory->create($parameters);
 
 
         $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
         $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
     }
     }
@@ -146,9 +146,9 @@ class ConnectionFactoryTest extends StandardTestCase
                 ->with($this->isType('string'), $this->isType('array'))
                 ->with($this->isType('string'), $this->isType('array'))
                 ->will($this->returnCallback($createCommand));
                 ->will($this->returnCallback($createCommand));
 
 
-        $factory = new ConnectionFactory();
+        $factory = new ConnectionFactory($profile);
         $parameters = new ConnectionParameters(array('database' => $database, 'password' => $password));
         $parameters = new ConnectionParameters(array('database' => $database, 'password' => $password));
-        $connection = $factory->create($parameters, $profile);
+        $connection = $factory->create($parameters);
 
 
         $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
         $this->assertInstanceOf('Predis\Connection\SingleConnectionInterface', $connection);
         $this->assertEquals(2, count($commands));   // TODO: assertCount()?
         $this->assertEquals(2, count($commands));   // TODO: assertCount()?
@@ -156,6 +156,29 @@ class ConnectionFactoryTest extends StandardTestCase
         $this->assertEquals(array($password), $commands['auth']);
         $this->assertEquals(array($password), $commands['auth']);
     }
     }
 
 
+    /**
+     * @group disconnected
+     * @todo This test smells but there's no other way around it right now.
+     */
+    public function testCreateConnectionWithDatabaseAndPasswordButNoProfile()
+    {
+        $parameters = new ConnectionParameters(array('database' => 0, 'password' => 'foobar'));
+
+        $connection = $this->getMock('Predis\Connection\SingleConnectionInterface');
+        $connection->expects($this->never())
+                   ->method('getParameters')
+                   ->will($this->returnValue($parameters));
+        $connection->expects($this->never())
+                   ->method('pushInitCommand');
+
+        $factory = new ConnectionFactory();
+
+        $reflection = new \ReflectionObject($factory);
+        $prepareConnection = $reflection->getMethod('prepareConnection');
+        $prepareConnection->setAccessible(true);
+        $prepareConnection->invoke($factory, $connection);
+    }
+
     /**
     /**
      * @group disconnected
      * @group disconnected
      */
      */
@@ -299,7 +322,7 @@ class ConnectionFactoryTest extends StandardTestCase
         $factory = $this->getMock('Predis\Connection\ConnectionFactory', array('create'));
         $factory = $this->getMock('Predis\Connection\ConnectionFactory', array('create'));
         $factory->expects($this->exactly(3))
         $factory->expects($this->exactly(3))
                 ->method('create')
                 ->method('create')
-                ->will($this->returnCallback(function ($_, $_) use ($connectionClass) {
+                ->will($this->returnCallback(function ($_) use ($connectionClass) {
                     return new $connectionClass;
                     return new $connectionClass;
                 }));
                 }));
 
 
@@ -331,16 +354,16 @@ class ConnectionFactoryTest extends StandardTestCase
         $cluster = $this->getMock('Predis\Connection\ClusterConnectionInterface');
         $cluster = $this->getMock('Predis\Connection\ClusterConnectionInterface');
         $profile = $this->getMock('Predis\Profile\ServerProfileInterface');
         $profile = $this->getMock('Predis\Profile\ServerProfileInterface');
 
 
-        $factory = $this->getMock('Predis\Connection\ConnectionFactory', array('create'));
+        $factory = $this->getMock('Predis\Connection\ConnectionFactory', array('create'), array($profile));
         $factory->expects($this->exactly(2))
         $factory->expects($this->exactly(2))
                 ->method('create')
                 ->method('create')
-                ->with($this->anything(), $profile)
-                ->will($this->returnCallback(function ($_, $_) use ($connectionClass) {
+                ->with($this->anything())
+                ->will($this->returnCallback(function ($_) use ($connectionClass) {
                     return new $connectionClass();
                     return new $connectionClass();
                 }));
                 }));
 
 
         $nodes = array('tcp://127.0.0.1:7001?password=foo', 'tcp://127.0.0.1:7002?password=bar');
         $nodes = array('tcp://127.0.0.1:7001?password=foo', 'tcp://127.0.0.1:7002?password=bar');
-        $factory->createAggregated($cluster, $nodes, $profile);
+        $factory->createAggregated($cluster, $nodes);
     }
     }