Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b05fce2

Browse files
committed
Merge branch '3.4'
* 3.4: A DI tag for resettable services. Add default templates directory and option to configure it Feature #23583 Add current and fallback locales in WDT / Profiler
2 parents 3e4f978 + 70bfb50 commit b05fce2

File tree

20 files changed

+372
-3
lines changed

20 files changed

+372
-3
lines changed

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
3434
use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
3535
use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass;
36+
use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass;
3637
use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass;
3738
use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass;
3839
use Symfony\Component\Serializer\DependencyInjection\SerializerPass;
@@ -106,6 +107,7 @@ public function build(ContainerBuilder $container)
106107
$container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING);
107108
$this->addCompilerPassIfExists($container, FormPass::class);
108109
$container->addCompilerPass(new WorkflowGuardListenerPass());
110+
$container->addCompilerPass(new ResettableServicePass());
109111

110112
if ($container->getParameter('kernel.debug')) {
111113
$container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32);

src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,11 @@
6060
<service id="Symfony\Component\Config\Resource\SelfCheckingResourceChecker">
6161
<tag name="config_cache.resource_checker" priority="-990" />
6262
</service>
63+
64+
<service id="Symfony\Component\HttpKernel\EventListener\ServiceResetListener">
65+
<argument /> <!-- ResettableServicePass will inject an iterator of initialized services here ($serviceId => $serviceInstance) -->
66+
<argument type="collection" /> <!-- ResettableServicePass will inject an array of reset methods here ($serviceId => $method) -->
67+
<tag name="kernel.event_subscriber" />
68+
</service>
6369
</services>
6470
</container>

src/Symfony/Bundle/TwigBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ CHANGELOG
1111

1212
* deprecated `Symfony\Bundle\TwigBundle\Command\DebugCommand`, use `Symfony\Bridge\Twig\Command\DebugCommand` instead
1313
* deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand`
14+
* added option to configure default path templates (via `default_path`)
1415

1516
3.3.0
1617
-----

src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode)
130130
->booleanNode('strict_variables')->end()
131131
->scalarNode('auto_reload')->end()
132132
->integerNode('optimizations')->min(-1)->end()
133+
->scalarNode('default_path')
134+
->info('The default path used to load templates')
135+
->defaultValue('%kernel.project_dir%/templates')
136+
->end()
133137
->arrayNode('paths')
134138
->normalizeKeys(false)
135139
->useAttributeAsKey('paths')

src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function load(array $configs, ContainerBuilder $container)
109109
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
110110
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']);
111111

112-
$bundleHierarchy = $this->getBundleHierarchy($container);
112+
$bundleHierarchy = $this->getBundleHierarchy($container, $config);
113113

114114
foreach ($bundleHierarchy as $name => $bundle) {
115115
$namespace = $this->normalizeBundleName($name);
@@ -130,6 +130,11 @@ public function load(array $configs, ContainerBuilder $container)
130130
}
131131
$container->addResource(new FileExistenceResource($dir));
132132

133+
if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']))) {
134+
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir));
135+
}
136+
$container->addResource(new FileExistenceResource($dir));
137+
133138
if (!empty($config['globals'])) {
134139
$def = $container->getDefinition('twig');
135140
foreach ($config['globals'] as $key => $global) {
@@ -161,7 +166,7 @@ public function load(array $configs, ContainerBuilder $container)
161166
$container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime');
162167
}
163168

164-
private function getBundleHierarchy(ContainerBuilder $container)
169+
private function getBundleHierarchy(ContainerBuilder $container, array $config)
165170
{
166171
$bundleHierarchy = array();
167172

@@ -179,6 +184,11 @@ private function getBundleHierarchy(ContainerBuilder $container)
179184
}
180185
$container->addResource(new FileExistenceResource($dir));
181186

187+
if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']).'/bundles/'.$name)) {
188+
$bundleHierarchy[$name]['paths'][] = $dir;
189+
}
190+
$container->addResource(new FileExistenceResource($dir));
191+
182192
if (file_exists($dir = $bundle['path'].'/Resources/views')) {
183193
$bundleHierarchy[$name]['paths'][] = $dir;
184194
}

src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
<xsd:attribute name="debug" type="xsd:string" />
2727
<xsd:attribute name="strict-variables" type="xsd:string" />
2828
<xsd:attribute name="exception-controller" type="xsd:string" />
29+
<xsd:attribute name="default-path" type="xsd:string" />
2930
</xsd:complexType>
3031

3132
<xsd:complexType name="date">

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
'charset' => 'ISO-8859-1',
1818
'debug' => true,
1919
'strict_variables' => true,
20+
'default_path' => '%kernel.root_dir%/templates',
2021
'paths' => array(
2122
'path1',
2223
'path2',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is a layout

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
77
http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd">
88

9-
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true">
9+
<twig:config auto-reload="true" autoescape="true" base-template-class="stdClass" cache="/tmp" charset="ISO-8859-1" debug="true" strict-variables="true" default-path="%kernel.root_dir%/templates">
1010
<twig:form-theme>MyBundle::form.html.twig</twig:form-theme>
1111
<twig:global key="foo" id="bar" type="service" />
1212
<twig:global key="baz">@@qux</twig:global>

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ twig:
1313
charset: ISO-8859-1
1414
debug: true
1515
strict_variables: true
16+
default_path: '%kernel.root_dir%/templates'
1617
paths:
1718
path1: ''
1819
path2: ''

src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ public function testTwigLoaderPaths($format)
196196
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'Twig'),
197197
array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'Twig'),
198198
array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'),
199+
array(__DIR__.'/Fixtures/templates/bundles/TwigBundle', 'Twig'),
199200
array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'),
200201
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
201202
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
@@ -205,6 +206,7 @@ public function testTwigLoaderPaths($format)
205206
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
206207
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
207208
array(__DIR__.'/Fixtures/Resources/views'),
209+
array(__DIR__.'/Fixtures/templates'),
208210
), $paths);
209211
}
210212

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
{% endset %}
1313

1414
{% set text %}
15+
<div class="sf-toolbar-info-piece">
16+
<b>Locale</b>
17+
<span class="sf-toolbar-status">
18+
{{ collector.locale|default('-') }}
19+
</span>
20+
</div>
1521
<div class="sf-toolbar-info-piece">
1622
<b>Missing messages</b>
1723
<span class="sf-toolbar-status sf-toolbar-status-{{ collector.countMissings ? 'red' }}">
@@ -61,6 +67,20 @@
6167
{% endblock %}
6268

6369
{% block panelContent %}
70+
71+
<h2>Translation Locales</h2>
72+
73+
<div class="metrics">
74+
<div class="metric">
75+
<span class="value">{{ collector.locale|default('-') }}</span>
76+
<span class="label">Locale</span>
77+
</div>
78+
<div class="metric">
79+
<span class="value">{{ collector.fallbackLocales|join(', ')|default('-') }}</span>
80+
<span class="label">Fallback locales</span>
81+
</div>
82+
</div>
83+
6484
<h2>Translation Metrics</h2>
6585

6686
<div class="metrics">
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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\HttpKernel\DependencyInjection;
13+
14+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
15+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
19+
use Symfony\Component\DependencyInjection\Reference;
20+
use Symfony\Component\HttpKernel\EventListener\ServiceResetListener;
21+
22+
/**
23+
* @author Alexander M. Turek <[email protected]>
24+
*/
25+
class ResettableServicePass implements CompilerPassInterface
26+
{
27+
private $tagName;
28+
29+
/**
30+
* @param string $tagName
31+
*/
32+
public function __construct($tagName = 'kernel.reset')
33+
{
34+
$this->tagName = $tagName;
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
public function process(ContainerBuilder $container)
41+
{
42+
if (!$container->has(ServiceResetListener::class)) {
43+
return;
44+
}
45+
46+
$services = $methods = array();
47+
48+
foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) {
49+
$services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE);
50+
$attributes = $tags[0];
51+
52+
if (!isset($attributes['method'])) {
53+
throw new RuntimeException(sprintf('Tag %s requires the "method" attribute to be set.', $this->tagName));
54+
}
55+
56+
$methods[$id] = $attributes['method'];
57+
}
58+
59+
if (empty($services)) {
60+
$container->removeDefinition(ServiceResetListener::class);
61+
62+
return;
63+
}
64+
65+
$container->findDefinition(ServiceResetListener::class)
66+
->replaceArgument(0, new IteratorArgument($services))
67+
->replaceArgument(1, $methods);
68+
}
69+
}
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\HttpKernel\EventListener;
13+
14+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
15+
use Symfony\Component\HttpKernel\KernelEvents;
16+
17+
/**
18+
* Clean up services between requests.
19+
*
20+
* @author Alexander M. Turek <[email protected]>
21+
*/
22+
class ServiceResetListener implements EventSubscriberInterface
23+
{
24+
private $services;
25+
private $resetMethods;
26+
27+
public function __construct(\Traversable $services, array $resetMethods)
28+
{
29+
$this->services = $services;
30+
$this->resetMethods = $resetMethods;
31+
}
32+
33+
public function onKernelTerminate()
34+
{
35+
foreach ($this->services as $id => $service) {
36+
$method = $this->resetMethods[$id];
37+
$service->$method();
38+
}
39+
}
40+
41+
/**
42+
* {@inheritdoc}
43+
*/
44+
public static function getSubscribedEvents()
45+
{
46+
return array(
47+
KernelEvents::TERMINATE => array('onKernelTerminate', -2048),
48+
);
49+
}
50+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\ContainerInterface;
9+
use Symfony\Component\DependencyInjection\Reference;
10+
use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass;
11+
use Symfony\Component\HttpKernel\EventListener\ServiceResetListener;
12+
use Symfony\Component\HttpKernel\Tests\Fixtures\ClearableService;
13+
use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService;
14+
15+
class ResettableServicePassTest extends TestCase
16+
{
17+
public function testCompilerPass()
18+
{
19+
$container = new ContainerBuilder();
20+
$container->register('one', ResettableService::class)
21+
->addTag('kernel.reset', array('method' => 'reset'));
22+
$container->register('two', ClearableService::class)
23+
->addTag('kernel.reset', array('method' => 'clear'));
24+
25+
$container->register(ServiceResetListener::class)
26+
->setArguments(array(null, array()));
27+
$container->addCompilerPass(new ResettableServicePass('kernel.reset'));
28+
29+
$container->compile();
30+
31+
$definition = $container->getDefinition(ServiceResetListener::class);
32+
33+
$this->assertEquals(
34+
array(
35+
new IteratorArgument(array(
36+
'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE),
37+
'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE),
38+
)),
39+
array(
40+
'one' => 'reset',
41+
'two' => 'clear',
42+
),
43+
),
44+
$definition->getArguments()
45+
);
46+
}
47+
48+
/**
49+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
50+
* @expectedExceptionMessage Tag kernel.reset requires the "method" attribute to be set.
51+
*/
52+
public function testMissingMethod()
53+
{
54+
$container = new ContainerBuilder();
55+
$container->register(ResettableService::class)
56+
->addTag('kernel.reset');
57+
$container->register(ServiceResetListener::class)
58+
->setArguments(array(null, array()));
59+
$container->addCompilerPass(new ResettableServicePass('kernel.reset'));
60+
61+
$container->compile();
62+
}
63+
64+
public function testCompilerPassWithoutResetters()
65+
{
66+
$container = new ContainerBuilder();
67+
$container->register(ServiceResetListener::class)
68+
->setArguments(array(null, array()));
69+
$container->addCompilerPass(new ResettableServicePass());
70+
71+
$container->compile();
72+
73+
$this->assertFalse($container->has(ServiceResetListener::class));
74+
}
75+
76+
public function testCompilerPassWithoutListener()
77+
{
78+
$container = new ContainerBuilder();
79+
$container->addCompilerPass(new ResettableServicePass());
80+
81+
$container->compile();
82+
83+
$this->assertFalse($container->has(ServiceResetListener::class));
84+
}
85+
}

0 commit comments

Comments
 (0)