Extend "commands" option to support Predis\Command\RawFactory.

The option handler has been extended to accept descriptive string values
in order to create and configure an appropriate command factory.

Accepted string values are:

- "predis" creates the usual command factory
- "raw" creates a raw command factory
- "default" is simply an alias of "predis"
This commit is contained in:
Daniele Alessandri
2020-08-29 20:33:15 +02:00
parent 30a065ad86
commit dc067b3dac
2 changed files with 176 additions and 14 deletions
+88 -14
View File
@@ -12,6 +12,7 @@
namespace Predis\Configuration\Option;
use Predis\Command\FactoryInterface;
use Predis\Command\RawFactory;
use Predis\Command\RedisFactory;
use Predis\Configuration\OptionInterface;
use Predis\Configuration\OptionsInterface;
@@ -32,27 +33,100 @@ class Commands implements OptionInterface
$value = call_user_func($value, $options);
}
if (is_array($value)) {
$commands = $this->getDefault($options);
if ($value instanceof FactoryInterface) {
return $value;
} elseif (is_array($value)) {
return $this->createFactoryByArray($options, $value);
} elseif(is_string($value)) {
return $this->createFactoryByString($options, $value);
} else {
throw new \InvalidArgumentException(sprintf(
'%s expects a valid command factory',
static::class
));
}
}
foreach ($value as $commandID => $commandClass) {
if ($commandClass === null) {
$commands->undefine($commandID);
} else {
$commands->define($commandID, $commandClass);
}
/**
* Creates a new default command factory from a named array.
*
* The factory instance is configured according to the supplied named array
* mapping command IDs (passed as keys) to the FCQN of classes implementing
* Predis\Command\CommandInterface.
*
* @param OptionsInterface $options Client options container
* @param array $value Named array mapping command IDs to classes
*
* @return FactoryInterface
*/
protected function createFactoryByArray(OptionsInterface $options, array $value)
{
/**
* @var FactoryInterface
*/
$commands = $this->getDefault($options);
foreach ($value as $commandID => $commandClass) {
if ($commandClass === null) {
$commands->undefine($commandID);
} else {
$commands->define($commandID, $commandClass);
}
return $commands;
}
if (!$value instanceof FactoryInterface) {
$class = get_called_class();
return $commands;
}
/**
* Creates a new command factory from a descriptive string.
*
* The factory instance is configured according to the supplied descriptive
* string that identifies specific configurations of schemes and connection
* classes. Supported configuration values are:
*
* - "predis" returns the default command factory used by Predis
* - "raw" returns a command factory that creates only raw commands
* - "default" is simply an alias of "predis"
*
* @param OptionsInterface $options Client options container
* @param string $value Descriptive string identifying the desired configuration
*
* @return FactoryInterface
*/
protected function createFactoryByString(OptionsInterface $options, string $value)
{
switch (strtolower($value)) {
case 'default':
case 'predis':
return $this->getDefault($options);
throw new \InvalidArgumentException("$class expects a valid command factory");
case 'raw':
return $this->createRawFactory($options);
default:
throw new \InvalidArgumentException(sprintf(
'%s does not recognize `%s` as a supported configuration string',
static::class,
$value
));
}
}
/**
* Creates a new raw command factory instance.
*
* @param OptionsInterface $options Client options container
*/
protected function createRawFactory(OptionsInterface $options): FactoryInterface
{
$commands = new RawFactory();
if (isset($options->prefix)) {
throw new \InvalidArgumentException(sprintf(
'%s does not support key prefixing', RawFactory::class
));
}
return $value;
return $commands;
}
/**
@@ -11,7 +11,10 @@
namespace Predis\Configuration\Option;
use PHPUnit\Framework\MockObject\MockObject;
use Predis\Configuration\OptionsInterface;
use Predis\Command\Processor\KeyPrefixProcessor;
use Predis\Command\RawFactory;
use Predis\Command\RedisFactory;
use PredisTestCase;
@@ -176,6 +179,70 @@ class CommandsTest extends PredisTestCase
$this->assertSame('Predis\Command\RawCommand', $commands->getCommandClass('BAR'));
}
/**
* @group disconnected
*/
public function testAcceptsStringPredisAsValue(): void
{
$option = new Commands();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$commands = $option->filter($options, 'predis');
$this->assertInstanceOf('Predis\Command\FactoryInterface', $commands);
$this->assertInstanceOf('Predis\Command\RedisFactory', $commands);
}
/**
* @group disconnected
*/
public function testAcceptsStringRawAsValue(): void
{
$option = new Commands();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$commands = $option->filter($options, 'raw');
$this->assertInstanceOf('Predis\Command\FactoryInterface', $commands);
$this->assertInstanceOf('Predis\Command\RawFactory', $commands);
}
/**
* @group disconnected
*/
public function testAcceptsStringDefaultAsValue(): void
{
$option = new Commands();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$commands = $option->filter($options, 'default');
$this->assertInstanceOf('Predis\Command\FactoryInterface', $commands);
$this->assertInstanceOf('Predis\Command\RedisFactory', $commands);
}
/**
* @group disconnected
*/
public function testThrowsExceptionOnInvalidStringAsValue()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('Predis\Configuration\Option\Commands does not recognize `unknown` as a supported configuration string');
$option = new Commands();
/** @var OptionsInterface */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$option->filter($options, 'unknown');
}
/**
* @group disconnected
*/
@@ -215,4 +282,25 @@ class CommandsTest extends PredisTestCase
$option->filter($options, new \stdClass());
}
/**
* @group disconnected
*/
public function testThrowsExceptionOnPrefixWithRawFactory(): void
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('Predis\Command\RawFactory does not support key prefixing');
$option = new Commands();
/** @var OptionsInterface|MockObject */
$options = $this->getMockBuilder('Predis\Configuration\OptionsInterface')->getMock();
$options
->expects($this->once())
->method('__isset')
->with('prefix')
->willReturn(true);
$option->filter($options, 'raw');
}
}