Skip to content

Commit eca09e9

Browse files
committed
feature #22619 [FrameworkBundle][Translation] Move translation compiler pass (lepiaf)
This PR was merged into the 3.4 branch. Discussion ---------- [FrameworkBundle][Translation] Move translation compiler pass | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes | Fixed tickets | part of #21284 | License | MIT | Doc PR | n/a move TranslationDumperPass, TranslationExtractorPass, TranslatorPass to Translation component. Commits ------- 74c951fa04 [FrameworkBundle][Translation] Move translation compiler pass
2 parents 58a4b77 + e0e4007 commit eca09e9

File tree

8 files changed

+380
-0
lines changed

8 files changed

+380
-0
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
CHANGELOG
22
=========
33

4+
3.4.0
5+
-----
6+
7+
* Added `TranslationDumperPass`
8+
* Added `TranslationExtractorPass`
9+
* Added `TranslatorPass`
10+
411
3.2.0
512
-----
613

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\DependencyInjection;
13+
14+
use Symfony\Component\DependencyInjection\Reference;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17+
18+
/**
19+
* Adds tagged translation.formatter services to translation writer.
20+
*/
21+
class TranslationDumperPass implements CompilerPassInterface
22+
{
23+
private $writerServiceId;
24+
private $dumperTag;
25+
26+
public function __construct($writerServiceId = 'translation.writer', $dumperTag = 'translation.dumper')
27+
{
28+
$this->writerServiceId = $writerServiceId;
29+
$this->dumperTag = $dumperTag;
30+
}
31+
32+
public function process(ContainerBuilder $container)
33+
{
34+
if (!$container->hasDefinition($this->writerServiceId)) {
35+
return;
36+
}
37+
38+
$definition = $container->getDefinition($this->writerServiceId);
39+
40+
foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) {
41+
$definition->addMethodCall('addDumper', array($attributes[0]['alias'], new Reference($id)));
42+
}
43+
}
44+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\DependencyInjection;
13+
14+
use Symfony\Component\DependencyInjection\Reference;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
18+
19+
/**
20+
* Adds tagged translation.extractor services to translation extractor.
21+
*/
22+
class TranslationExtractorPass implements CompilerPassInterface
23+
{
24+
private $extractorServiceId;
25+
private $extractorTag;
26+
27+
public function __construct($extractorServiceId = 'translation.extractor', $extractorTag = 'translation.extractor')
28+
{
29+
$this->extractorServiceId = $extractorServiceId;
30+
$this->extractorTag = $extractorTag;
31+
}
32+
33+
public function process(ContainerBuilder $container)
34+
{
35+
if (!$container->hasDefinition($this->extractorServiceId)) {
36+
return;
37+
}
38+
39+
$definition = $container->getDefinition($this->extractorServiceId);
40+
41+
foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) {
42+
if (!isset($attributes[0]['alias'])) {
43+
throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id));
44+
}
45+
46+
$definition->addMethodCall('addExtractor', array($attributes[0]['alias'], new Reference($id)));
47+
}
48+
}
49+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\DependencyInjection;
13+
14+
use Symfony\Component\DependencyInjection\Reference;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
17+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
18+
19+
class TranslatorPass implements CompilerPassInterface
20+
{
21+
private $translatorServiceId;
22+
private $loaderServiceId;
23+
private $loaderTag;
24+
25+
public function __construct($translatorServiceId = 'translator.default', $loaderServiceId = 'translation.loader', $loaderTag = 'translation.loader')
26+
{
27+
$this->translatorServiceId = $translatorServiceId;
28+
$this->loaderServiceId = $loaderServiceId;
29+
$this->loaderTag = $loaderTag;
30+
}
31+
32+
public function process(ContainerBuilder $container)
33+
{
34+
if (!$container->hasDefinition($this->translatorServiceId)) {
35+
return;
36+
}
37+
38+
$loaders = array();
39+
$loaderRefs = array();
40+
foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) {
41+
$loaderRefs[$id] = new Reference($id);
42+
$loaders[$id][] = $attributes[0]['alias'];
43+
if (isset($attributes[0]['legacy-alias'])) {
44+
$loaders[$id][] = $attributes[0]['legacy-alias'];
45+
}
46+
}
47+
48+
if ($container->hasDefinition($this->loaderServiceId)) {
49+
$definition = $container->getDefinition($this->loaderServiceId);
50+
foreach ($loaders as $id => $formats) {
51+
foreach ($formats as $format) {
52+
$definition->addMethodCall('addLoader', array($format, $loaderRefs[$id]));
53+
}
54+
}
55+
}
56+
57+
$container
58+
->findDefinition($this->translatorServiceId)
59+
->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs))
60+
->replaceArgument(3, $loaders)
61+
;
62+
}
63+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\Tests\DependencyInjection;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Reference;
16+
use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass;
17+
18+
class TranslationDumperPassTest extends TestCase
19+
{
20+
public function testProcess()
21+
{
22+
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock();
23+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock();
24+
25+
$container->expects($this->once())
26+
->method('hasDefinition')
27+
->with('translation.writer')
28+
->will($this->returnValue(true));
29+
30+
$container->expects($this->once())
31+
->method('getDefinition')
32+
->with('translation.writer')
33+
->will($this->returnValue($definition));
34+
35+
$valueTaggedServiceIdsFound = array(
36+
'foo.id' => array(
37+
array('alias' => 'bar.alias'),
38+
),
39+
);
40+
$container->expects($this->once())
41+
->method('findTaggedServiceIds')
42+
->with('translation.dumper', true)
43+
->will($this->returnValue($valueTaggedServiceIdsFound));
44+
45+
$definition->expects($this->once())->method('addMethodCall')->with('addDumper', array('bar.alias', new Reference('foo.id')));
46+
47+
$translationDumperPass = new TranslationDumperPass();
48+
$translationDumperPass->process($container);
49+
}
50+
51+
public function testProcessNoDefinitionFound()
52+
{
53+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock();
54+
55+
$container->expects($this->once())
56+
->method('hasDefinition')
57+
->with('translation.writer')
58+
->will($this->returnValue(false));
59+
60+
$container->expects($this->never())->method('getDefinition');
61+
$container->expects($this->never())->method('findTaggedServiceIds');
62+
63+
$translationDumperPass = new TranslationDumperPass();
64+
$translationDumperPass->process($container);
65+
}
66+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\Tests\DependencyInjection;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Reference;
16+
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
17+
18+
class TranslationExtractorPassTest extends TestCase
19+
{
20+
public function testProcess()
21+
{
22+
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock();
23+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock();
24+
25+
$container->expects($this->once())
26+
->method('hasDefinition')
27+
->with('translation.extractor')
28+
->will($this->returnValue(true));
29+
30+
$container->expects($this->once())
31+
->method('getDefinition')
32+
->with('translation.extractor')
33+
->will($this->returnValue($definition));
34+
35+
$valueTaggedServiceIdsFound = array(
36+
'foo.id' => array(
37+
array('alias' => 'bar.alias'),
38+
),
39+
);
40+
$container->expects($this->once())
41+
->method('findTaggedServiceIds')
42+
->with('translation.extractor', true)
43+
->will($this->returnValue($valueTaggedServiceIdsFound));
44+
45+
$definition->expects($this->once())->method('addMethodCall')->with('addExtractor', array('bar.alias', new Reference('foo.id')));
46+
47+
$translationDumperPass = new TranslationExtractorPass();
48+
$translationDumperPass->process($container);
49+
}
50+
51+
public function testProcessNoDefinitionFound()
52+
{
53+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock();
54+
55+
$container->expects($this->once())
56+
->method('hasDefinition')
57+
->with('translation.extractor')
58+
->will($this->returnValue(false));
59+
60+
$container->expects($this->never())->method('getDefinition');
61+
$container->expects($this->never())->method('findTaggedServiceIds');
62+
63+
$translationDumperPass = new TranslationExtractorPass();
64+
$translationDumperPass->process($container);
65+
}
66+
67+
/**
68+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
69+
* @expectedExceptionMessage The alias for the tag "translation.extractor" of service "foo.id" must be set.
70+
*/
71+
public function testProcessMissingAlias()
72+
{
73+
$definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock();
74+
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock();
75+
76+
$container->expects($this->once())
77+
->method('hasDefinition')
78+
->with('translation.extractor')
79+
->will($this->returnValue(true));
80+
81+
$container->expects($this->once())
82+
->method('getDefinition')
83+
->with('translation.extractor')
84+
->will($this->returnValue($definition));
85+
86+
$valueTaggedServiceIdsFound = array(
87+
'foo.id' => array(),
88+
);
89+
$container->expects($this->once())
90+
->method('findTaggedServiceIds')
91+
->with('translation.extractor', true)
92+
->will($this->returnValue($valueTaggedServiceIdsFound));
93+
94+
$definition->expects($this->never())->method('addMethodCall');
95+
96+
$translationDumperPass = new TranslationExtractorPass();
97+
$translationDumperPass->process($container);
98+
}
99+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\Translation\Tests\DependencyInjection;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Definition;
18+
use Symfony\Component\DependencyInjection\Reference;
19+
use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
20+
21+
class TranslationPassTest extends TestCase
22+
{
23+
public function testValidCollector()
24+
{
25+
$loader = (new Definition())
26+
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'));
27+
28+
$translator = (new Definition())
29+
->setArguments(array(null, null, null, null));
30+
31+
$container = new ContainerBuilder();
32+
$container->setDefinition('translator.default', $translator);
33+
$container->setDefinition('translation.loader', $loader);
34+
35+
$pass = new TranslatorPass();
36+
$pass->process($container);
37+
38+
$expected = (new Definition())
39+
->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf'))
40+
->addMethodCall('addLoader', array('xliff', new Reference('translation.loader')))
41+
->addMethodCall('addLoader', array('xlf', new Reference('translation.loader')))
42+
;
43+
$this->assertEquals($expected, $loader);
44+
45+
$this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3));
46+
47+
$expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader')));
48+
$this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0));
49+
}
50+
}

0 commit comments

Comments
 (0)