Skip to content

Commit

Permalink
Merge pull request #335 from php-enqueue/bundle-better-dx-when-transp…
Browse files Browse the repository at this point in the history
…ort-is-missing

[bundle][dx] Add a message that suggest installing a pkg to use the transport.
  • Loading branch information
makasim authored Jan 18, 2018
2 parents 6558467 + 58f62cf commit a12b06c
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 7 deletions.
32 changes: 25 additions & 7 deletions pkg/enqueue-bundle/EnqueueBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Enqueue\Stomp\Symfony\RabbitMqStompTransportFactory;
use Enqueue\Stomp\Symfony\StompTransportFactory;
use Enqueue\Symfony\AmqpTransportFactory;
use Enqueue\Symfony\MissingTransportFactory;
use Enqueue\Symfony\RabbitMqAmqpTransportFactory;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand All @@ -53,8 +54,11 @@ public function build(ContainerBuilder $container)
$extension = $container->getExtension('enqueue');

if (class_exists(StompConnectionFactory::class)) {
$extension->addTransportFactory(new StompTransportFactory());
$extension->addTransportFactory(new RabbitMqStompTransportFactory());
$extension->addTransportFactory(new StompTransportFactory('stomp'));
$extension->addTransportFactory(new RabbitMqStompTransportFactory('rabbitmq_stomp'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('stomp', ['enqueue/stomp']));
$extension->addTransportFactory(new MissingTransportFactory('rabbitmq_stomp', ['enqueue/stomp']));
}

if (
Expand All @@ -64,26 +68,40 @@ class_exists(AmqpLibConnectionFactory::class)
) {
$extension->addTransportFactory(new AmqpTransportFactory('amqp'));
$extension->addTransportFactory(new RabbitMqAmqpTransportFactory('rabbitmq_amqp'));
} else {
$amppPackages = ['enqueue/amqp-ext', 'enqueue/amqp-bunny', 'enqueue/amqp-lib'];
$extension->addTransportFactory(new MissingTransportFactory('amqp', $amppPackages));
$extension->addTransportFactory(new MissingTransportFactory('rabbitmq_amqp', $amppPackages));
}

if (class_exists(FsConnectionFactory::class)) {
$extension->addTransportFactory(new FsTransportFactory());
$extension->addTransportFactory(new FsTransportFactory('fs'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('fs', ['enqueue/fs']));
}

if (class_exists(RedisConnectionFactory::class)) {
$extension->addTransportFactory(new RedisTransportFactory());
$extension->addTransportFactory(new RedisTransportFactory('redis'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('redis', ['enqueue/redis']));
}

if (class_exists(DbalConnectionFactory::class)) {
$extension->addTransportFactory(new DbalTransportFactory());
$extension->addTransportFactory(new DbalTransportFactory('dbal'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('dbal', ['enqueue/dbal']));
}

if (class_exists(SqsConnectionFactory::class)) {
$extension->addTransportFactory(new SqsTransportFactory());
$extension->addTransportFactory(new SqsTransportFactory('sqs'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('sqs', ['enqueue/sqs']));
}

if (class_exists(GpsConnectionFactory::class)) {
$extension->addTransportFactory(new GpsTransportFactory());
$extension->addTransportFactory(new GpsTransportFactory('gps'));
} else {
$extension->addTransportFactory(new MissingTransportFactory('gps', ['enqueue/gps']));
}

$container->addCompilerPass(new AsyncEventsPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
use Enqueue\Null\NullContext;
use Enqueue\Null\Symfony\NullTransportFactory;
use Enqueue\Symfony\DefaultTransportFactory;
use Enqueue\Symfony\MissingTransportFactory;
use Enqueue\Symfony\TransportFactoryInterface;
use Enqueue\Test\ClassExtensionTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
Expand Down Expand Up @@ -569,4 +571,20 @@ public function testShouldConfigureQueueConsumer()
$this->assertSame(123, $def->getArgument(2));
$this->assertSame(456, $def->getArgument(3));
}

public function testShouldThrowIfPackageShouldBeInstalledToUseTransport()
{
$container = new ContainerBuilder();

$extension = new EnqueueExtension();
$extension->addTransportFactory(new MissingTransportFactory('need_package', ['a_package', 'another_package']));

$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage('In order to use the transport "need_package" install');
$extension->load([[
'transport' => [
'need_package' => true,
],
]], $container);
}
}
94 changes: 94 additions & 0 deletions pkg/enqueue/Symfony/MissingTransportFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Enqueue\Symfony;

use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class MissingTransportFactory implements TransportFactoryInterface, DriverFactoryInterface
{
/**
* @var string
*/
private $name;
/**
* @var string[]
*/
private $packages;

/**
* @param string $name
* @param string[] $packages
*/
public function __construct($name, array $packages)
{
$this->name = $name;
$this->packages = $packages;
}

/**
* {@inheritdoc}
*/
public function addConfiguration(ArrayNodeDefinition $builder)
{
if (1 == count($this->packages)) {
$message = sprintf(
'In order to use the transport "%s" install a package "%s"',
$this->getName(),
implode('", "', $this->packages)
);
} else {
$message = sprintf(
'In order to use the transport "%s" install one of the packages "%s"',
$this->getName(),
implode('", "', $this->packages)
);
}

$builder
->info($message)
->beforeNormalization()
->always(function () {
return [];
})
->end()
->validate()
->always(function () use ($message) {
throw new \InvalidArgumentException($message);
})
->end()
;
}

/**
* {@inheritdoc}
*/
public function createConnectionFactory(ContainerBuilder $container, array $config)
{
throw new \LogicException('Should not be called');
}

/**
* {@inheritdoc}
*/
public function createContext(ContainerBuilder $container, array $config)
{
throw new \LogicException('Should not be called');
}

/**
* {@inheritdoc}
*/
public function createDriver(ContainerBuilder $container, array $config)
{
throw new \LogicException('Should not be called');
}

/**
* @return string
*/
public function getName()
{
return $this->name;
}
}
73 changes: 73 additions & 0 deletions pkg/enqueue/Tests/Symfony/MissingTransportFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

namespace Enqueue\Tests\Symfony;

use Enqueue\Symfony\MissingTransportFactory;
use Enqueue\Symfony\TransportFactoryInterface;
use Enqueue\Test\ClassExtensionTrait;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
use Symfony\Component\Config\Definition\Processor;

class MissingTransportFactoryTest extends TestCase
{
use ClassExtensionTrait;

public function testShouldImplementTransportFactoryInterface()
{
$this->assertClassImplements(TransportFactoryInterface::class, MissingTransportFactory::class);
}

public function testCouldBeConstructedWithNameAndPackages()
{
$transport = new MissingTransportFactory('aMissingTransportName', ['aPackage', 'anotherPackage']);

$this->assertEquals('aMissingTransportName', $transport->getName());
}

public function testThrowOnProcessForOnePackageToInstall()
{
$transport = new MissingTransportFactory('aMissingTransportName', ['aFooPackage']);
$tb = new TreeBuilder();
$rootNode = $tb->root('foo');

$transport->addConfiguration($rootNode);
$processor = new Processor();

$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage('Invalid configuration for path "foo": In order to use the transport "aMissingTransportName" install a package "aFooPackage"');
$processor->process($tb->buildTree(), [[]]);
}

public function testThrowOnProcessForSeveralPackagesToInstall()
{
$transport = new MissingTransportFactory('aMissingTransportName', ['aFooPackage', 'aBarPackage']);
$tb = new TreeBuilder();
$rootNode = $tb->root('foo');

$transport->addConfiguration($rootNode);
$processor = new Processor();

$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage('Invalid configuration for path "foo": In order to use the transport "aMissingTransportName" install one of the packages "aFooPackage", "aBarPackage"');
$processor->process($tb->buildTree(), [[]]);
}

public function testThrowEvenIfThereAreSomeOptionsPassed()
{
$transport = new MissingTransportFactory('aMissingTransportName', ['aFooPackage', 'aBarPackage']);
$tb = new TreeBuilder();
$rootNode = $tb->root('foo');

$transport->addConfiguration($rootNode);
$processor = new Processor();

$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage('In order to use the transport "aMissingTransportName"');
$processor->process($tb->buildTree(), [[
'foo' => 'fooVal',
'bar' => 'barVal',
]]);
}
}

0 comments on commit a12b06c

Please sign in to comment.