8000 feature #18482 Created a trait to sort tagged services (iltar) · symfony/symfony@f8dc459 · GitHub
[go: up one dir, main page]

Skip to content

Commit f8dc459

Browse files
committed
feature #18482 Created a trait to sort tagged services (iltar)
This PR was squashed before being merged into the 3.2-dev branch (closes #18482). Discussion ---------- Created a trait to sort tagged services | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | ~ | License | MIT | Doc PR | ~ When writing the `ControllerArgumentValueResolverPass`, I needed a sorting on `priority`. I ended up copying a method from another class. I noticed this was done more often and 99% of the code was the same. I've moved the most common notation into the trait and "used" the trait in the priority aware passes. This increases horizontal re-use and means people can also use this in their bundles. The cases that were slightly different, are still working completely. I had to fix some tests because they returned an invalid value from the mocked find method. Commits ------- 778a70b Created a trait to sort tagged services
2 parents 31678c9 + 778a70b commit f8dc459

File tree

9 files changed

+158
-119
lines changed

9 files changed

+158
-119
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1415
use Symfony\Component\DependencyInjection\ContainerBuilder;
1516
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16-
use Symfony\Component\DependencyInjection\Reference;
1717

1818
/**
1919
* Registers the cache warmers.
@@ -22,6 +22,8 @@
2222
*/
2323
class AddCacheWarmerPass implements CompilerPassInterface
2424
{
25+
use PriorityTaggedServiceTrait;
26+
2527
/**
2628
* {@inheritdoc}
2729
*/
@@ -31,20 +33,12 @@ public function process(ContainerBuilder $container)
3133
return;
3234
}
3335

34-
$warmers = array();
35-
foreach ($container->findTaggedServiceIds('kernel.cache_warmer') as $id => $attributes) {
36-
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
37-
$warmers[$priority][] = new Reference($id);
38-
}
36+
$warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container);
3937

4038
if (empty($warmers)) {
4139
return;
4240
}
4341

44-
// sort by priority and flatten
45-
krsort($warmers);
46-
$warmers = call_user_func_array('array_merge', $warmers);
47-
4842
$container->getDefinition('cache_warmer')->replaceArgument(0, $warmers);
4943
}
5044
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
16-
use Symfony\Component\DependencyInjection\Reference;
1717

1818
/**
1919
* Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority.
@@ -23,23 +23,16 @@
2323
*/
2424
class ConfigCachePass implements CompilerPassInterface
2525
{
26+
use PriorityTaggedServiceTrait;
27+
2628
public function process(ContainerBuilder $container)
2729
{
28-
$resourceCheckers = array();
29-
30-
foreach ($container->findTaggedServiceIds('config_cache.resource_checker') as $id => $tags) {
31-
$priority = isset($tags[0]['priority']) ? $tags[0]['priority'] : 0;
32-
$resourceCheckers[$priority][] = new Reference($id);
33-
}
30+
$resourceCheckers = $this->findAndSortTaggedServices('config_cache.resource_checker', $container);
3431

3532
if (empty($resourceCheckers)) {
3633
return;
3734
}
3835

39-
// sort by priority and flatten
40-
krsort($resourceCheckers);
41-
$resourceCheckers = call_user_func_array('array_merge', $resourceCheckers);
42-
4336
$container->getDefinition('config_cache_factory')->replaceArgument(0, $resourceCheckers);
4437
}
4538
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
16-
use Symfony\Component\DependencyInjection\Reference;
1717

1818
/**
1919
* Gathers and configures the argument value resolvers.
@@ -22,6 +22,8 @@
2222
*/
2323
class ControllerArgumentValueResolverPass implements CompilerPassInterface
2424
{
25+
use PriorityTaggedServiceTrait;
26+
2527
public function process(ContainerBuilder $container)
2628
{
2729
if (!$container->hasDefinition('argument_resolver')) {
@@ -32,34 +34,4 @@ public function process(ContainerBuilder $container)
3234
$argumentResolvers = $this->findAndSortTaggedServices('controller.argument_value_resolver', $container);
3335
$definition->replaceArgument(1, $argumentResolvers);
3436
}
35-
36-
/**
37-
* Finds all services with the given tag name and order them by their priority.
38-
*
39-
* @param string $tagName
40-
* @param ContainerBuilder $container
41-
*
42-
* @return array
43-
*/
44-
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
45-
{
46-
$services = $container->findTaggedServiceIds($tagName);
47-
48-
$sortedServices = array();
49-
foreach ($services as $serviceId => $tags) {
50-
foreach ($tags as $attributes) {
51-
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
52-
$sortedServices[$priority][] = new Reference($serviceId);
53-
}
54-
}
55-
56-
if (empty($sortedServices)) {
57-
return array();
58-
}
59-
60-
krsort($sortedServices);
61-
62-
// Flatten the array
63-
return call_user_func_array('array_merge', $sortedServices);
64-
}
6537
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
16-
use Symfony\Component\DependencyInjection\Reference;
1717

1818
/**
1919
* Adds extractors to the property_info service.
@@ -22,6 +22,8 @@
2222
*/
2323
class PropertyInfoPass implements CompilerPassInterface
2424
{
25+
use PriorityTaggedServiceTrait;
26+
2527
/**
2628
* {@inheritdoc}
2729
*/
@@ -45,34 +47,4 @@ public function process(ContainerBuilder $container)
4547
$accessExtractors = $this->findAndSortTaggedServices('property_info.access_extractor', $container);
4648
$definition->replaceArgument(3, $accessExtractors);
4749
}
48-
49-
/**
50-
* Finds all services with the given tag name and order them by their priority.
51-
*
52-
* @param string $tagName
53-
* @param ContainerBuilder $container
54-
*
55-
* @return array
56-
*/
57-
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
58-
{
59-
$services = $container->findTaggedServiceIds($tagName);
60-
61-
$sortedServices = array();
62-
foreach ($services as $serviceId => $tags) {
63-
foreach ($tags as $attributes) {
64-
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
65-
$sortedServices[$priority][] = new Reference($serviceId);
66-
}
67-
}
68-
69-
if (empty($sortedServices)) {
70-
return array();
71-
}
72-
73-
krsort($sortedServices);
74-
75-
// Flatten the array
76-
return call_user_func_array('array_merge', $sortedServices);
77-
}
7850
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
1415
use Symfony\Component\DependencyInjection\ContainerBuilder;
1516
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16-
use Symfony\Component\DependencyInjection\Reference;
1717

1818
/**
1919
* Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as
@@ -23,6 +23,8 @@
2323
*/
2424
class SerializerPass implements CompilerPassInterface
2525
{
26+
use PriorityTaggedServiceTrait;
27+
2628
public function process(ContainerBuilder $container)
2729
{
2830
if (!$container->hasDefinition('serializer')) {
@@ -31,42 +33,17 @@ public function process(ContainerBuilder $container)
3133

3234
// Looks for all the services tagged "serializer.normalizer" and adds them to the Serializer service
3335
$normalizers = $this->findAndSortTaggedServices('serializer.normalizer', $container);
36+
37+
if (empty($normalizers)) {
38+
throw new \RuntimeException('You must tag at least one service as "serializer.normalizer" to use the Serializer service');
39+
}
3440
$container->getDefinition('serializer')->replaceArgument(0, $normalizers);
3541

3642
// Looks for all the services tagged "serializer.encoders" and adds them to the Serializer service
3743
$encoders = $this->findAndSortTaggedServices('serializer.encoder', $container);
38-
$container->getDefinition('serializer')->replaceArgument(1, $encoders);
39-
}
40-
41-
/**
42-
* Finds all services with the given tag name and order them by their priority.
43-
*
44-
* @param string $tagName
45-
* @param ContainerBuilder $container
46-
*
47-
* @return array
48-
*
49-
* @throws \RuntimeException
50-
*/
51-
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
52-
{
53-
$services = $container->findTaggedServiceIds($tagName);
54-
55-
if (empty($services)) {
56-
throw new \RuntimeException(sprintf('You must tag at least one service as "%s" to use the Serializer service', $tagName));
57-
}
58-
59-
$sortedServices = array();
60-
foreach ($services as $serviceId => $tags) {
61-
foreach ($tags as $attributes) {
62-
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
63-
$sortedServices[$priority][] = new Reference($serviceId);
64-
}
44+
if (empty($encoders)) {
45+
throw new \RuntimeException('You must tag at least one service as "serializer.encoder" to use the Serializer service');
6546
}
66-
67-
krsort($sortedServices);
68-
69-
// Flatten the array
70-
return call_user_func_array('array_merge', $sortedServices);
47+
$container->getDefinition('serializer')->replaceArgument(1, $encoders);
7148
}
7249
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function testThatCacheWarmersAreProcessedInPriorityOrder()
2121
$services = array(
2222
'my_cache_warmer_service1' => array(0 => array('priority' => 100)),
2323
'my_cache_warmer_service2' => array(0 => array('priority' => 200)),
24-
'my_cache_warmer_service3' => array(),
24+
'my_cache_warmer_service3' => array(0 => array()),
2525
);
2626

2727
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function testThatCheckersAreProcessedInPriorityOrder()
2121
$services = array(
2222
'checker_2' => array(0 => array('priority' => 100)),
2323
'checker_1' => array(0 => array('priority' => 200)),
24-
'checker_3' => array(),
24+
'checker_3' => array(0 => array()),
2525
);
2626

2727
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
@@ -52,7 +52,6 @@ public function testThatCheckersAreProcessedInPriorityOrder()
5252

5353
public function testThatCheckersCanBeMissing()
5454
{
55-
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
5655
$container = $this->getMock(
5756
'Symfony\Component\DependencyInjection\ContainerBuilder',
5857
array('findTaggedServiceIds')
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.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+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Reference;
16+
17+
/**
18+
* Trait that allows a generic method to find and sort service by priority option in the tag.
19+
*
20+
* @author Iltar van der Berg <kjarli@gmail.com>
21+
*/
22+
trait PriorityTaggedServiceTrait
23+
{
24+
/**
25+
* Finds all services with the given tag name and order them by their priority.
26+
*
27+
* @param string $tagName
28+
* @param ContainerBuilder $container
29+
*
30+
* @return Reference[]
31+
*/
32+
private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
33+
{
34+
$services = $container->findTaggedServiceIds($tagName);
35+
36+
$queue = new \SplPriorityQueue();
37+
38+
foreach ($services as $serviceId => $tags) {
39+
foreach ($tags as $attributes) {
40+
$priority = isset($attributes['priority']) ? $attributes['priority'] : 0;
41+
$queue->insert(new Reference($serviceId), $priority * -1);
42+
}
43+
}
44+
45+
return iterator_to_array($queue);
46+
}
47+
}

0 commit comments

Comments
 (0)
0