Skip to content

Commit da6ebcd

Browse files
authored
Merge pull request #72 from php-enqueue/client-extensions
[WIP] Client Extensions
2 parents 0c76d8d + 1ac0989 commit da6ebcd

File tree

12 files changed

+400
-14
lines changed

12 files changed

+400
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace Enqueue\Bundle\DependencyInjection\Compiler;
4+
5+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
6+
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
use Symfony\Component\DependencyInjection\Reference;
8+
9+
class BuildClientExtensionsPass implements CompilerPassInterface
10+
{
11+
/**
12+
* {@inheritdoc}
13+
*/
14+
public function process(ContainerBuilder $container)
15+
{
16+
if (false == $container->hasDefinition('enqueue.client.extensions')) {
17+
return;
18+
}
19+
20+
$tags = $container->findTaggedServiceIds('enqueue.client.extension');
21+
22+
$groupByPriority = [];
23+
foreach ($tags as $serviceId => $tagAttributes) {
24+
foreach ($tagAttributes as $tagAttribute) {
25+
$priority = isset($tagAttribute['priority']) ? (int) $tagAttribute['priority'] : 0;
26+
27+
$groupByPriority[$priority][] = new Reference($serviceId);
28+
}
29+
}
30+
31+
krsort($groupByPriority, SORT_NUMERIC);
32+
33+
$flatExtensions = [];
34+
foreach ($groupByPriority as $extension) {
35+
$flatExtensions = array_merge($flatExtensions, $extension);
36+
}
37+
38+
$container->getDefinition('enqueue.client.extensions')->replaceArgument(0, $flatExtensions);
39+
}
40+
}

pkg/enqueue-bundle/DependencyInjection/Compiler/BuildExtensionsPass.php renamed to pkg/enqueue-bundle/DependencyInjection/Compiler/BuildConsumptionExtensionsPass.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use Symfony\Component\DependencyInjection\ContainerBuilder;
77
use Symfony\Component\DependencyInjection\Reference;
88

9-
class BuildExtensionsPass implements CompilerPassInterface
9+
class BuildConsumptionExtensionsPass implements CompilerPassInterface
1010
{
1111
/**
1212
* {@inheritdoc}

pkg/enqueue-bundle/EnqueueBundle.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
use Enqueue\AmqpExt\AmqpContext;
66
use Enqueue\AmqpExt\Symfony\AmqpTransportFactory;
77
use Enqueue\AmqpExt\Symfony\RabbitMqAmqpTransportFactory;
8+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildClientExtensionsPass;
89
use Enqueue\Bundle\DependencyInjection\Compiler\BuildClientRoutingPass;
9-
use Enqueue\Bundle\DependencyInjection\Compiler\BuildExtensionsPass;
10+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildConsumptionExtensionsPass;
1011
use Enqueue\Bundle\DependencyInjection\Compiler\BuildProcessorRegistryPass;
1112
use Enqueue\Bundle\DependencyInjection\Compiler\BuildQueueMetaRegistryPass;
1213
use Enqueue\Bundle\DependencyInjection\Compiler\BuildTopicMetaSubscribersPass;
@@ -34,11 +35,12 @@ class EnqueueBundle extends Bundle
3435
*/
3536
public function build(ContainerBuilder $container)
3637
{
37-
$container->addCompilerPass(new BuildExtensionsPass());
38+
$container->addCompilerPass(new BuildConsumptionExtensionsPass());
3839
$container->addCompilerPass(new BuildClientRoutingPass());
3940
$container->addCompilerPass(new BuildProcessorRegistryPass());
4041
$container->addCompilerPass(new BuildTopicMetaSubscribersPass());
4142
$container->addCompilerPass(new BuildQueueMetaRegistryPass());
43+
$container->addCompilerPass(new BuildClientExtensionsPass());
4244

4345
/** @var EnqueueExtension $extension */
4446
$extension = $container->getExtension('enqueue');

pkg/enqueue-bundle/Resources/config/client.yml

+9-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@ services:
55

66
enqueue.client.producer:
77
class: 'Enqueue\Client\Producer'
8-
arguments: ['@enqueue.client.driver']
8+
arguments:
9+
- '@enqueue.client.driver'
10+
- '@enqueue.client.extensions'
11+
12+
enqueue.client.extensions:
13+
class: 'Enqueue\Client\ChainExtension'
14+
public: false
15+
arguments:
16+
- []
917

1018
enqueue.producer:
1119
alias: 'enqueue.client.producer'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
namespace Enqueue\Bundle\Tests\Unit\DependencyInjection\Compiler;
4+
5+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildClientExtensionsPass;
6+
use Enqueue\Test\ClassExtensionTrait;
7+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
8+
use Symfony\Component\DependencyInjection\ContainerBuilder;
9+
use Symfony\Component\DependencyInjection\Definition;
10+
use Symfony\Component\DependencyInjection\Reference;
11+
use PHPUnit\Framework\TestCase;
12+
13+
class BuildClientExtensionsPassTest extends TestCase
14+
{
15+
use ClassExtensionTrait;
16+
17+
public function testShouldImplementCompilerPass()
18+
{
19+
$this->assertClassImplements(CompilerPassInterface::class, BuildClientExtensionsPass::class);
20+
}
21+
22+
public function testCouldBeConstructedWithoutAnyArguments()
23+
{
24+
new BuildClientExtensionsPass();
25+
}
26+
27+
public function testShouldReplaceFirstArgumentOfExtensionsServiceConstructorWithTaggsExtensions()
28+
{
29+
$container = new ContainerBuilder();
30+
31+
$extensions = new Definition();
32+
$extensions->addArgument([]);
33+
$container->setDefinition('enqueue.client.extensions', $extensions);
34+
35+
$extension = new Definition();
36+
$extension->addTag('enqueue.client.extension');
37+
$container->setDefinition('foo_extension', $extension);
38+
39+
$extension = new Definition();
40+
$extension->addTag('enqueue.client.extension');
41+
$container->setDefinition('bar_extension', $extension);
42+
43+
$pass = new BuildClientExtensionsPass();
44+
$pass->process($container);
45+
46+
$this->assertEquals(
47+
[new Reference('foo_extension'), new Reference('bar_extension')],
48+
$extensions->getArgument(0)
49+
);
50+
}
51+
52+
public function testShouldOrderExtensionsByPriority()
53+
{
54+
$container = new ContainerBuilder();
55+
56+
$extensions = new Definition();
57+
$extensions->addArgument([]);
58+
$container->setDefinition('enqueue.client.extensions', $extensions);
59+
60+
$extension = new Definition();
61+
$extension->addTag('enqueue.client.extension', ['priority' => 6]);
62+
$container->setDefinition('foo_extension', $extension);
63+
64+
$extension = new Definition();
65+
$extension->addTag('enqueue.client.extension', ['priority' => -5]);
66+
$container->setDefinition('bar_extension', $extension);
67+
68+
$extension = new Definition();
69+
$extension->addTag('enqueue.client.extension', ['priority' => 2]);
70+
$container->setDefinition('baz_extension', $extension);
71+
72+
$pass = new BuildClientExtensionsPass();
73+
$pass->process($container);
74+
75+
$orderedExtensions = $extensions->getArgument(0);
76+
77+
$this->assertEquals(new Reference('foo_extension'), $orderedExtensions[0]);
78+
$this->assertEquals(new Reference('baz_extension'), $orderedExtensions[1]);
79+
$this->assertEquals(new Reference('bar_extension'), $orderedExtensions[2]);
80+
}
81+
82+
public function testShouldAssumePriorityZeroIfPriorityIsNotSet()
83+
{
84+
$container = new ContainerBuilder();
85+
86+
$extensions = new Definition();
87+
$extensions->addArgument([]);
88+
$container->setDefinition('enqueue.client.extensions', $extensions);
89+
90+
$extension = new Definition();
91+
$extension->addTag('enqueue.client.extension');
92+
$container->setDefinition('foo_extension', $extension);
93+
94+
$extension = new Definition();
95+
$extension->addTag('enqueue.client.extension', ['priority' => 1]);
96+
$container->setDefinition('bar_extension', $extension);
97+
98+
$extension = new Definition();
99+
$extension->addTag('enqueue.client.extension', ['priority' => -1]);
100+
$container->setDefinition('baz_extension', $extension);
101+
102+
$pass = new BuildClientExtensionsPass();
103+
$pass->process($container);
104+
105+
$orderedExtensions = $extensions->getArgument(0);
106+
107+
$this->assertEquals(new Reference('bar_extension'), $orderedExtensions[0]);
108+
$this->assertEquals(new Reference('foo_extension'), $orderedExtensions[1]);
109+
$this->assertEquals(new Reference('baz_extension'), $orderedExtensions[2]);
110+
}
111+
112+
public function testShouldDoesNothingIfClientExtensionServiceIsNotDefined()
113+
{
114+
$container = $this->createMock(ContainerBuilder::class);
115+
$container
116+
->expects($this->once())
117+
->method('hasDefinition')
118+
->with('enqueue.client.extensions')
119+
->willReturn(false)
120+
;
121+
$container
122+
->expects($this->never())
123+
->method('findTaggedServiceIds')
124+
;
125+
126+
$pass = new BuildClientExtensionsPass();
127+
$pass->process($container);
128+
}
129+
}

pkg/enqueue-bundle/Tests/Unit/DependencyInjection/Compiler/BuildExtensionsPassTest.php renamed to pkg/enqueue-bundle/Tests/Unit/DependencyInjection/Compiler/BuildConsumptionExtensionsPassTest.php

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@
22

33
namespace Enqueue\Bundle\Tests\Unit\DependencyInjection\Compiler;
44

5-
use Enqueue\Bundle\DependencyInjection\Compiler\BuildExtensionsPass;
5+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildConsumptionExtensionsPass;
66
use Enqueue\Test\ClassExtensionTrait;
77
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
88
use Symfony\Component\DependencyInjection\ContainerBuilder;
99
use Symfony\Component\DependencyInjection\Definition;
1010
use Symfony\Component\DependencyInjection\Reference;
1111
use PHPUnit\Framework\TestCase;
1212

13-
class BuildExtensionsPassTest extends TestCase
13+
class BuildConsumptionExtensionsPassTest extends TestCase
1414
{
1515
use ClassExtensionTrait;
1616

1717
public function testShouldImplementCompilerPass()
1818
{
19-
$this->assertClassImplements(CompilerPassInterface::class, BuildExtensionsPass::class);
19+
$this->assertClassImplements(CompilerPassInterface::class, BuildConsumptionExtensionsPass::class);
2020
}
2121

2222
public function testCouldBeConstructedWithoutAnyArguments()
2323
{
24-
new BuildExtensionsPass();
24+
new BuildConsumptionExtensionsPass();
2525
}
2626

2727
public function testShouldReplaceFirstArgumentOfExtensionsServiceConstructorWithTaggsExtensions()
@@ -40,7 +40,7 @@ public function testShouldReplaceFirstArgumentOfExtensionsServiceConstructorWith
4040
$extension->addTag('enqueue.consumption.extension');
4141
$container->setDefinition('bar_extension', $extension);
4242

43-
$pass = new BuildExtensionsPass();
43+
$pass = new BuildConsumptionExtensionsPass();
4444
$pass->process($container);
4545

4646
$this->assertEquals(
@@ -69,7 +69,7 @@ public function testShouldOrderExtensionsByPriority()
6969
$extension->addTag('enqueue.consumption.extension', ['priority' => 2]);
7070
$container->setDefinition('baz_extension', $extension);
7171

72-
$pass = new BuildExtensionsPass();
72+
$pass = new BuildConsumptionExtensionsPass();
7373
$pass->process($container);
7474

7575
$orderedExtensions = $extensions->getArgument(0);
@@ -99,7 +99,7 @@ public function testShouldAssumePriorityZeroIfPriorityIsNotSet()
9999
$extension->addTag('enqueue.consumption.extension', ['priority' => -1]);
100100
$container->setDefinition('baz_extension', $extension);
101101

102-
$pass = new BuildExtensionsPass();
102+
$pass = new BuildConsumptionExtensionsPass();
103103
$pass->process($container);
104104

105105
$orderedExtensions = $extensions->getArgument(0);

pkg/enqueue-bundle/Tests/Unit/EnqueueBundleTest.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
use Enqueue\AmqpExt\Symfony\AmqpTransportFactory;
66
use Enqueue\AmqpExt\Symfony\RabbitMqAmqpTransportFactory;
7+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildClientExtensionsPass;
78
use Enqueue\Bundle\DependencyInjection\Compiler\BuildClientRoutingPass;
8-
use Enqueue\Bundle\DependencyInjection\Compiler\BuildExtensionsPass;
9+
use Enqueue\Bundle\DependencyInjection\Compiler\BuildConsumptionExtensionsPass;
910
use Enqueue\Bundle\DependencyInjection\Compiler\BuildProcessorRegistryPass;
1011
use Enqueue\Bundle\DependencyInjection\Compiler\BuildQueueMetaRegistryPass;
1112
use Enqueue\Bundle\DependencyInjection\Compiler\BuildTopicMetaSubscribersPass;
@@ -46,7 +47,7 @@ public function testShouldRegisterExpectedCompilerPasses()
4647
$container
4748
->expects($this->at(0))
4849
->method('addCompilerPass')
49-
->with($this->isInstanceOf(BuildExtensionsPass::class))
50+
->with($this->isInstanceOf(BuildConsumptionExtensionsPass::class))
5051
;
5152
$container
5253
->expects($this->at(1))
@@ -70,6 +71,11 @@ public function testShouldRegisterExpectedCompilerPasses()
7071
;
7172
$container
7273
->expects($this->at(5))
74+
->method('addCompilerPass')
75+
->with($this->isInstanceOf(BuildClientExtensionsPass::class))
76+
;
77+
$container
78+
->expects($this->at(6))
7379
->method('getExtension')
7480
->willReturn($extensionMock)
7581
;

pkg/enqueue/Client/ChainExtension.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Enqueue\Client;
4+
5+
class ChainExtension implements ExtensionInterface
6+
{
7+
/**
8+
* @var ExtensionInterface[]
9+
*/
10+
private $extensions;
11+
12+
/**
13+
* @param ExtensionInterface[] $extensions
14+
*/
15+
public function __construct(array $extensions)
16+
{
17+
$this->extensions = $extensions;
18+
}
19+
20+
/**
21+
* {@inheritdoc}
22+
*/
23+
public function onPreSend($topic, Message $message)
24+
{
25+
foreach ($this->extensions as $extension) {
26+
$extension->onPreSend($topic, $message);
27+
}
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function onPostSend($topic, Message $message)
34+
{
35+
foreach ($this->extensions as $extension) {
36+
$extension->onPostSend($topic, $message);
37+
}
38+
}
39+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
namespace Enqueue\Client;
3+
4+
interface ExtensionInterface
5+
{
6+
/**
7+
* @param string $topic
8+
* @param Message $message
9+
* @return
10+
*/
11+
public function onPreSend($topic, Message $message);
12+
13+
/**
14+
* @param string $topic
15+
* @param Message $message
16+
* @return
17+
*/
18+
public function onPostSend($topic, Message $message);
19+
}

0 commit comments

Comments
 (0)