Skip to content

Commit 8a84413

Browse files
committed
sort tagged service by priority
add test by priority tags
1 parent 588890a commit 8a84413

11 files changed

+308
-9
lines changed

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php

+21
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,27 @@ protected function sortServiceIds(array $serviceIds)
289289
return $serviceIds;
290290
}
291291

292+
public function sortTaggedServicesByPriority(array $services): array
293+
{
294+
$maxPriority = [];
295+
foreach ($services as $name => $tags) {
296+
if (!isset($maxPriority[$name])) {
297+
$maxPriority[$name] = 0;
298+
}
299+
foreach ($tags as $tag) {
300+
$currentPriority = $tag['priority'] ?? 0;
301+
if ($maxPriority[$name] < $currentPriority) {
302+
$maxPriority[$name] = $currentPriority;
303+
}
304+
}
305+
}
306+
uasort($maxPriority, function ($a, $b) {
307+
return $b <=> $a;
308+
});
309+
310+
return array_keys($maxPriority);
311+
}
312+
292313
/**
293314
* Gets class description from a docblock.
294315
*/

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ protected function describeContainerService($service, array $options = [], Conta
100100
*/
101101
protected function describeContainerServices(ContainerBuilder $builder, array $options = [])
102102
{
103-
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
103+
$serviceIds = isset($options['tag']) && $options['tag']
104+
? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag']))
105+
: $this->sortServiceIds($builder->getServiceIds());
104106
$showHidden = isset($options['show_hidden']) && $options['show_hidden'];
105107
$omitTags = isset($options['omit_tags']) && $options['omit_tags'];
106108
$showArguments = isset($options['show_arguments']) && $options['show_arguments'];
@@ -110,7 +112,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
110112
$serviceIds = array_filter($serviceIds, $options['filter']);
111113
}
112114

113-
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
115+
foreach ($serviceIds as $serviceId) {
114116
$service = $this->resolveServiceDefinition($builder, $serviceId);
115117

116118
if ($showHidden xor '.' === ($serviceId[0] ?? null)) {

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,17 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
132132
}
133133
$this->write($title."\n".str_repeat('=', \strlen($title)));
134134

135-
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
135+
$serviceIds = isset($options['tag']) && $options['tag']
136+
? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag']))
137+
: $this->sortServiceIds($builder->getServiceIds());
136138
$showArguments = isset($options['show_arguments']) && $options['show_arguments'];
137139
$services = ['definitions' => [], 'aliases' => [], 'services' => []];
138140

139141
if (isset($options['filter'])) {
140142
$serviceIds = array_filter($serviceIds, $options['filter']);
141143
}
142144

143-
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
145+
foreach ($serviceIds as $serviceId) {
144146
$service = $this->resolveServiceDefinition($builder, $serviceId);
145147

146148
if ($showHidden xor '.' === ($serviceId[0] ?? null)) {

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,9 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
191191

192192
$options['output']->title($title);
193193

194-
$serviceIds = isset($options['tag']) && $options['tag'] ? array_keys($builder->findTaggedServiceIds($options['tag'])) : $builder->getServiceIds();
194+
$serviceIds = isset($options['tag']) && $options['tag']
195+
? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($options['tag']))
196+
: $this->sortServiceIds($builder->getServiceIds());
195197
$maxTags = [];
196198

197199
if (isset($options['filter'])) {
@@ -230,7 +232,7 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
230232
$tableHeaders = array_merge(['Service ID'], $tagsNames, ['Class name']);
231233
$tableRows = [];
232234
$rawOutput = isset($options['raw_text']) && $options['raw_text'];
233-
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
235+
foreach ($serviceIds as $serviceId) {
234236
$definition = $this->resolveServiceDefinition($builder, $serviceId);
235237

236238
$styledServiceId = $rawOutput ? $serviceId : sprintf('<fg=cyan>%s</fg=cyan>', OutputFormatter::escape($serviceId));

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php

+4-3
Original file line numberDiff line numberDiff line change
@@ -287,13 +287,14 @@ private function getContainerServicesDocument(ContainerBuilder $builder, string
287287
$dom = new \DOMDocument('1.0', 'UTF-8');
288288
$dom->appendChild($containerXML = $dom->createElement('container'));
289289

290-
$serviceIds = $tag ? array_keys($builder->findTaggedServiceIds($tag)) : $builder->getServiceIds();
291-
290+
$serviceIds = $tag
291+
? $this->sortTaggedServicesByPriority($builder->findTaggedServiceIds($tag))
292+
: $this->sortServiceIds($builder->getServiceIds());
292293
if ($filter) {
293294
$serviceIds = array_filter($serviceIds, $filter);
294295
}
295296

296-
foreach ($this->sortServiceIds($serviceIds) as $serviceId) {
297+
foreach ($serviceIds as $serviceId) {
297298
$service = $this->resolveServiceDefinition($builder, $serviceId);
298299

299300
if ($showHidden xor '.' === ($serviceId[0] ?? null)) {

src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php

+21
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,25 @@ private function getEventDispatcherDescriptionTestData(array $objects)
287287

288288
return $data;
289289
}
290+
291+
/** @dataProvider getDescribeContainerBuilderWithPriorityTagsTestData */
292+
public function testDescribeContainerBuilderWithPriorityTags(ContainerBuilder $builder, $expectedDescription, array $options): void
293+
{
294+
$this->assertDescription($expectedDescription, $builder, $options);
295+
}
296+
297+
public function getDescribeContainerBuilderWithPriorityTagsTestData(): array
298+
{
299+
$variations = ['priority_tag' => ['tag' => 'tag1']];
300+
$data = [];
301+
foreach (ObjectsProvider::getContainerBuildersWithPriorityTags() as $name => $object) {
302+
foreach ($variations as $suffix => $options) {
303+
$file = sprintf('%s_%s.%s', trim($name, '.'), $suffix, $this->getFormat());
304+
$description = file_get_contents(__DIR__.'/../../Fixtures/Descriptor/'.$file);
305+
$data[] = [$object, $description, $options, $file];
306+
}
307+
}
308+
309+
return $data;
310+
}
290311
}

src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php

+44
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,50 @@ public static function getContainerDefinitions()
144144
];
145145
}
146146

147+
public static function getContainerBuildersWithPriorityTags()
148+
{
149+
$builder = new ContainerBuilder();
150+
$builder->setDefinitions(self::getContainerDefinitionsWithPriorityTags());
151+
152+
return ['builder' => $builder];
153+
}
154+
155+
public static function getContainerDefinitionsWithPriorityTags()
156+
{
157+
$definition1 = new Definition('Full\\Qualified\\Class1');
158+
$definition2 = new Definition('Full\\Qualified\\Class2');
159+
$definition3 = new Definition('Full\\Qualified\\Class3');
160+
161+
return [
162+
'definition_1' => $definition1
163+
->setPublic(true)
164+
->setSynthetic(true)
165+
->setFile('/path/to/file')
166+
->setLazy(false)
167+
->setAbstract(false)
168+
->addTag('tag1', ['attr1' => 'val1', 'priority' => 30])
169+
->addTag('tag1', ['attr2' => 'val2'])
170+
->addTag('tag2')
171+
->addMethodCall('setMailer', [new Reference('mailer')])
172+
->setFactory([new Reference('factory.service'), 'get']),
173+
'definition_2' => $definition2
174+
->setPublic(true)
175+
->setSynthetic(true)
176+
->setFile('/path/to/file')
177+
->setLazy(false)
178+
->setAbstract(false)
179+
->addTag('tag1', ['attr1' => 'val1', 'attr2' => 'val2', 'priority' => -20]),
180+
'definition_3' => $definition3
181+
->setPublic(true)
182+
->setSynthetic(true)
183+
->setFile('/path/to/file')
184+
->setLazy(false)
185+
->setAbstract(false)
186+
->addTag('tag1', ['attr1' => 'val1', 'attr2' => 'val2', 'priority' => 0])
187+
->addTag('tag1', ['attr3' => 'val3', 'priority' => 40]),
188+
];
189+
}
190+
147191
public static function getContainerAliases()
148192
{
149193
return [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{
2+
"definitions": {
3+
"definition_3": {
4+
"class": "Full\\Qualified\\Class3",
5+
"public": true,
6+
"synthetic": true,
7+
"lazy": false,
8+
"shared": true,
9+
"abstract": false,
10+
"autowire": false,
11+
"autoconfigure": false,
12+
"file": "\/path\/to\/file",
13+
"tags": [
14+
{
15+
"name": "tag1",
16+
"parameters": {
17+
"attr1": "val1",
18+
"attr2": "val2",
19+
"priority": 0
20+
}
21+
},
22+
{
23+
"name": "tag1",
24+
"parameters": {
25+
"attr3": "val3",
26+
"priority": 40
27+
}
28+
}
29+
]
30+
},
31+
"definition_1": {
32+
"class": "Full\\Qualified\\Class1",
33+
"public": true,
34+
"synthetic": true,
35+
"lazy": false,
36+
"shared": true,
37+
"abstract": false,
38+
"autowire": false,
39+
"autoconfigure": false,
40+
"file": "\/path\/to\/file",
41+
"factory_service": "factory.service",
42+
"factory_method": "get",
43+
"calls": [
44+
"setMailer"
45+
],
46+
"tags": [
47+
{
48+
"name": "tag1",
49+
"parameters": {
50+
"attr1": "val1",
51+
"priority": 30
52+
}
53+
},
54+
{
55+
"name": "tag1",
56+
"parameters": {
57+
"attr2": "val2"
58+
}
59+
},
60+
{
61+
"name": "tag2",
62+
"parameters": []
63+
}
64+
]
65+
},
66+
"definition_2": {
67+
"class": "Full\\Qualified\\Class2",
68+
"public": true,
69+
"synthetic": true,
70+
"lazy": false,
71+
"shared": true,
72+
"abstract": false,
73+
"autowire": false,
74+
"autoconfigure": false,
75+
"file": "\/path\/to\/file",
76+
"tags": [
77+
{
78+
"name": "tag1",
79+
"parameters": {
80+
"attr1": "val1",
81+
"attr2": "val2",
82+
"priority": -20
83+
}
84+
}
85+
]
86+
}
87+
},
88+
"aliases": [],
89+
"services": []
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
Services with tag `tag1`
2+
========================
3+
4+
Definitions
5+
-----------
6+
7+
### definition_3
8+
9+
- Class: `Full\Qualified\Class3`
10+
- Public: yes
11+
- Synthetic: yes
12+
- Lazy: no
13+
- Shared: yes
14+
- Abstract: no
15+
- Autowired: no
16+
- Autoconfigured: no
17+
- File: `/path/to/file`
18+
- Tag: `tag1`
19+
- Attr1: val1
20+
- Attr2: val2
21+
- Priority: 0
22+
- Tag: `tag1`
23+
- Attr3: val3
24+
- Priority: 40
25+
26+
### definition_1
27+
28+
- Class: `Full\Qualified\Class1`
29+
- Public: yes
30+
- Synthetic: yes
31+
- Lazy: no
32+
- Shared: yes
33+
- Abstract: no
34+
- Autowired: no
35+
- Autoconfigured: no
36+
- File: `/path/to/file`
37+
- Factory Service: `factory.service`
38+
- Factory Method: `get`
39+
- Call: `setMailer`
40+
- Tag: `tag1`
41+
- Attr1: val1
42+
- Priority: 30
43+
- Tag: `tag1`
44+
- Attr2: val2
45+
- Tag: `tag2`
46+
47+
### definition_2
48+
49+
- Class: `Full\Qualified\Class2`
50+
- Public: yes
51+
- Synthetic: yes
52+
- Lazy: no
53+
- Shared: yes
54+
- Abstract: no
55+
- Autowired: no
56+
- Autoconfigured: no
57+
- File: `/path/to/file`
58+
- Tag: `tag1`
59+
- Attr1: val1
60+
- Attr2: val2
61+
- Priority: -20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
Symfony Container Services Tagged with "tag1" Tag
3+
=================================================
4+
5+
-------------- ------- ------- ---------- ------- -----------------------
6+
 Service ID   attr1   attr2   priority   attr3   Class name 
7+
-------------- ------- ------- ---------- ------- -----------------------
8+
definition_3 val1 val2 0 Full\Qualified\Class3
9+
" 40 val3
10+
definition_1 val1 30 Full\Qualified\Class1
11+
" val2
12+
definition_2 val1 val2 -20 Full\Qualified\Class2
13+
-------------- ------- ------- ---------- ------- -----------------------
14+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<container>
3+
<definition id="definition_3" class="Full\Qualified\Class3" public="true" synthetic="true" lazy="false" shared="true" abstract="false" autowired="false" autoconfigured="false" file="/path/to/file">
4+
<tags>
5+
<tag name="tag1">
6+
<parameter name="attr1">val1</parameter>
7+
<parameter name="attr2">val2</parameter>
8+
<parameter name="priority">0</parameter>
9+
</tag>
10+
<tag name="tag1">
11+
<parameter name="attr3">val3</parameter>
12+
<parameter name="priority">40</parameter>
13+
</tag>
14+
</tags>
15+
</definition>
16+
<definition id="definition_1" class="Full\Qualified\Class1" public="true" synthetic="true" lazy="false" shared="true" abstract="false" autowired="false" autoconfigured="false" file="/path/to/file">
17+
<factory service="factory.service" method="get"/>
18+
<calls>
19+
<call method="setMailer"/>
20+
</calls>
21+
<tags>
22+
<tag name="tag1">
23+
<parameter name="attr1">val1</parameter>
24+
<parameter name="priority">30</parameter>
25+
</tag>
26+
<tag name="tag1">
27+
<parameter name="attr2">val2</parameter>
28+
</tag>
29+
<tag name="tag2"/>
30+
</tags>
31+
</definition>
32+
<definition id="definition_2" class="Full\Qualified\Class2" public="true" synthetic="true" lazy="false" shared="true" abstract="false" autowired="false" autoconfigured="false" file="/path/to/file">
33+
<tags>
34+
<tag name="tag1">
35+
<parameter name="attr1">val1</parameter>
36+
<parameter name="attr2">val2</parameter>
37+
<parameter name="priority">-20</parameter>
38+
</tag>
39+
</tags>
40+
</definition>
41+
</container>

0 commit comments

Comments
 (0)