Skip to content

Commit 9fb8e8c

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 9713ac2 + 65963fe commit 9fb8e8c

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
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+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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\Tests\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Reference;
17+
18+
class PriorityTaggedServiceTraitTest extends \PHPUnit_Framework_TestCase
19+
{
20+
public function testThatCacheWarmersAreProcessedInPriorityOrder()
21+
{
22+
$services = array(
23+
'my_service1' => array(array('priority' => 100)),
24+
'my_service2' => array(array('priority' => 200)),
25+
'my_service3' => array(array('priority' => -500)),
26+
'my_service4' => array(array()),
27+
'my_service5' => array(array()),
28+
'my_service6' => array(array('priority' => -500)),
29+
'my_service7' => array(array('priority' => -499)),
30+
'my_service8' => array(array('priority' => 1)),
31+
'my_service9' => array(array()),
32+
'my_service10' => array(array('priority' => -1000)),
33+
'my_service11' => array(array('priority' => -1000)),
34+
'my_service12' => array(array('priority' => -1000)),
35+
'my_service13' => array(array('priority' => -1000)),
36+
);
37+
38+
$definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
39+
$container = $this->getMock(
40+
'Symfony\Component\DependencyInjection\ContainerBuilder',
41+
array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
42+
);
43+
44+
$container
45+
->expects($this->atLeastOnce())
46+
->method('findTaggedServiceIds')
47+
->will($this->returnValue($services));
48+
$container
49+
->expects($this->atLeastOnce())
50+
->method('getDefinition')
51+
->with('my_custom_tag')
52+
->will($this->returnValue($definition));
53+
54+
$definition
55+
->expects($this->once())
56+
->method('replaceArgument')
57+
->with(0, array(
58+
new Reference('my_service2'),
59+
new Reference('my_service1'),
60+
new Reference('my_service8'),
61+
new Reference('my_service4'),
62+
new Reference('my_service5'),
63+
new Reference('my_service9'),
64+
new Reference('my_service7'),
65+
new Reference('my_service3'),
66+
new Reference('my_service6'),
67+
new Reference('my_service10'),
68+
new Reference('my_service11'),
69+
new Reference('my_service12'),
70+
new Reference('my_service13'),
71+
));
72+
73+
(new PriorityTaggedServiceTraitImplementation())->test('my_custom_tag', $container);
74+
}
75+
}
76+
77+
class PriorityTaggedServiceTraitImplementation
78+
{
79+
use PriorityTaggedServiceTrait;
80+
81+
public function test($tagName, ContainerBuilder $container)
82+
{
83+
return $this->findAndSortTaggedServices($tagName, $container);
84+
}
85+
}

0 commit comments

Comments
 (0)