minor #24103 [FrameworkBundle] Fix Di config to allow for more private services (nicolas-grekas)
This PR was merged into the 3.4 branch.
Discussion
----------
[FrameworkBundle] Fix Di config to allow for more private services
| Q | A
| ------------- | ---
| Branch? | 3.4
| Bug fix? | no
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | -
| License | MIT
| Doc PR | -
This PR is a prelude to #23822:
- allow cache pool clearers to be private by using IGNORE_ON_UNINITIALIZED_REFERENCE, allowing much more sane logic in the related passes
- allow templating helpers to be private by using a service locator
- replace an inline def by a reference in workflow's config (ping @lyrixx @Nyholm)
- fix the Stopwatch alias, which is public in 3.4, but private in 3.3
- remove direct access to `->get('fragment.handler')` in tests so that the service could be made private
Commits
-------
76c42175b9
[FrameworkBundle] Fix Di config to allow for more private services
This commit is contained in:
commit
4f02e91592
@ -27,29 +27,16 @@ final class CachePoolClearerPass implements CompilerPassInterface
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$container->getParameterBag()->remove('cache.prefix.seed');
|
||||
$poolsByClearer = array();
|
||||
$pools = array();
|
||||
|
||||
foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) {
|
||||
$pools[$id] = new Reference($id);
|
||||
foreach (array_reverse($attributes) as $attr) {
|
||||
if (isset($attr['clearer'])) {
|
||||
$poolsByClearer[$attr['clearer']][$id] = $pools[$id];
|
||||
}
|
||||
if (!empty($attr['unlazy'])) {
|
||||
$container->getDefinition($id)->setLazy(false);
|
||||
}
|
||||
if (array_key_exists('clearer', $attr) || array_key_exists('unlazy', $attr)) {
|
||||
break;
|
||||
foreach ($container->findTaggedServiceIds('cache.pool.clearer') as $id => $attr) {
|
||||
$clearer = $container->getDefinition($id);
|
||||
$pools = array();
|
||||
foreach ($clearer->getArgument(0) as $id => $ref) {
|
||||
if ($container->hasDefinition($id)) {
|
||||
$pools[$id] = new Reference($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$container->getDefinition('cache.global_clearer')->addArgument($pools);
|
||||
|
||||
foreach ($poolsByClearer as $clearer => $pools) {
|
||||
$clearer = $container->getDefinition($clearer);
|
||||
$clearer->addArgument($pools);
|
||||
$clearer->replaceArgument(0, $pools);
|
||||
}
|
||||
|
||||
if (!$container->has('cache.annotations')) {
|
||||
|
@ -37,6 +37,8 @@ class CachePoolPass implements CompilerPassInterface
|
||||
}
|
||||
$seed .= '.'.$container->getParameter('kernel.name').'.'.$container->getParameter('kernel.environment');
|
||||
|
||||
$pools = array();
|
||||
$clearers = array();
|
||||
$attributes = array(
|
||||
'provider',
|
||||
'namespace',
|
||||
@ -47,10 +49,8 @@ class CachePoolPass implements CompilerPassInterface
|
||||
if ($pool->isAbstract()) {
|
||||
continue;
|
||||
}
|
||||
$isLazy = $pool->isLazy();
|
||||
while ($adapter instanceof ChildDefinition) {
|
||||
$adapter = $container->findDefinition($adapter->getParent());
|
||||
$isLazy = $isLazy || $adapter->isLazy();
|
||||
if ($t = $adapter->getTag('cache.pool')) {
|
||||
$tags[0] += $t[0];
|
||||
}
|
||||
@ -82,17 +82,29 @@ class CachePoolPass implements CompilerPassInterface
|
||||
throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0]))));
|
||||
}
|
||||
|
||||
$attr = array();
|
||||
if (null !== $clearer) {
|
||||
$attr['clearer'] = $clearer;
|
||||
$clearers[$clearer][$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
}
|
||||
if (!$isLazy) {
|
||||
$pool->setLazy(true);
|
||||
$attr['unlazy'] = true;
|
||||
}
|
||||
if ($attr) {
|
||||
$pool->addTag('cache.pool', $attr);
|
||||
|
||||
$pools[$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
|
||||
}
|
||||
|
||||
$clearer = 'cache.global_clearer';
|
||||
while ($container->hasAlias($clearer)) {
|
||||
$clearer = (string) $container->getAlias($clearer);
|
||||
}
|
||||
if ($container->hasDefinition($clearer)) {
|
||||
$clearers['cache.global_clearer'] = $pools;
|
||||
}
|
||||
|
||||
foreach ($clearers as $id => $pools) {
|
||||
$clearer = $container->getDefinition($id);
|
||||
if ($clearer instanceof ChilDefinition) {
|
||||
$clearer->replaceArgument(0, $pools);
|
||||
} else {
|
||||
$clearer->setArgument(0, $pools);
|
||||
}
|
||||
$clearer->addTag('cache.pool.clearer');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@ use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundle
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface;
|
||||
|
||||
class TemplatingPass implements CompilerPassInterface
|
||||
@ -31,16 +32,22 @@ class TemplatingPass implements CompilerPassInterface
|
||||
}
|
||||
|
||||
if ($container->hasDefinition('templating.engine.php')) {
|
||||
$refs = array();
|
||||
$helpers = array();
|
||||
foreach ($container->findTaggedServiceIds('templating.helper', true) as $id => $attributes) {
|
||||
if (isset($attributes[0]['alias'])) {
|
||||
$helpers[$attributes[0]['alias']] = $id;
|
||||
$refs[$id] = new Reference($id);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($helpers) > 0) {
|
||||
$definition = $container->getDefinition('templating.engine.php');
|
||||
$definition->addMethodCall('setHelpers', array($helpers));
|
||||
|
||||
if ($container->hasDefinition('templating.engine.php.helpers_locator')) {
|
||||
$container->getDefinition('templating.engine.php.helpers_locator')->replaceArgument(0, $refs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
class UnusedTagsPass implements CompilerPassInterface
|
||||
{
|
||||
private $whitelist = array(
|
||||
'cache.pool.clearer',
|
||||
'console.command',
|
||||
'container.service_locator',
|
||||
'container.service_subscriber',
|
||||
|
@ -597,15 +597,15 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
|
||||
// Create Workflow
|
||||
$workflowId = sprintf('%s.%s', $type, $name);
|
||||
$workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type));
|
||||
$workflowDefinition->replaceArgument(0, $definitionDefinition);
|
||||
$workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId)));
|
||||
if (isset($markingStoreDefinition)) {
|
||||
$workflowDefinition->replaceArgument(1, $markingStoreDefinition);
|
||||
}
|
||||
$workflowDefinition->replaceArgument(3, $name);
|
||||
|
||||
// Store to container
|
||||
$workflowId = sprintf('%s.%s', $type, $name);
|
||||
$container->setDefinition($workflowId, $workflowDefinition);
|
||||
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
|
||||
|
||||
@ -680,7 +680,7 @@ class FrameworkExtension extends Extension
|
||||
|
||||
if (class_exists(Stopwatch::class)) {
|
||||
$container->register('debug.stopwatch', Stopwatch::class)->addArgument(true);
|
||||
$container->setAlias(Stopwatch::class, 'debug.stopwatch');
|
||||
$container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false));
|
||||
}
|
||||
|
||||
$debug = $container->getParameter('kernel.debug');
|
||||
|
@ -106,7 +106,7 @@ class FrameworkBundle extends Bundle
|
||||
$container->addCompilerPass(new AddExpressionLanguageProvidersPass());
|
||||
$this->addCompilerPassIfExists($container, TranslationExtractorPass::class);
|
||||
$this->addCompilerPassIfExists($container, TranslationDumperPass::class);
|
||||
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
|
||||
$container->addCompilerPass(new FragmentRendererPass());
|
||||
$this->addCompilerPassIfExists($container, SerializerPass::class);
|
||||
$this->addCompilerPassIfExists($container, PropertyInfoPass::class);
|
||||
$container->addCompilerPass(new DataCollectorTranslatorPass());
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<service id="debug.templating.engine.php" class="Symfony\Bundle\FrameworkBundle\Templating\TimedPhpEngine">
|
||||
<argument type="service" id="templating.name_parser" />
|
||||
<argument type="service" id="service_container" />
|
||||
<argument type="service" id="templating.engine.php.helpers_locator" />
|
||||
<argument type="service" id="templating.loader" />
|
||||
<argument type="service" id="debug.stopwatch" />
|
||||
<argument type="service" id="templating.globals" />
|
||||
|
@ -9,12 +9,17 @@
|
||||
|
||||
<service id="templating.engine.php" class="Symfony\Bundle\FrameworkBundle\Templating\PhpEngine">
|
||||
<argument type="service" id="templating.name_parser" />
|
||||
<argument type="service" id="service_container" />
|
||||
<argument type="service" id="templating.engine.php.helpers_locator" />
|
||||
<argument type="service" id="templating.loader" />
|
||||
<argument type="service" id="templating.globals" />
|
||||
<call method="setCharset"><argument>%kernel.charset%</argument></call>
|
||||
</service>
|
||||
|
||||
<service id="templating.engine.php.helpers_locator">
|
||||
<tag name="container.service_locator" />
|
||||
<argument type="collection" />
|
||||
</service>
|
||||
|
||||
<service id="templating.helper.slots" class="Symfony\Component\Templating\Helper\SlotsHelper" public="true">
|
||||
<tag name="templating.helper" alias="slots" />
|
||||
</service>
|
||||
|
@ -226,7 +226,7 @@ class FormHelper extends Helper
|
||||
* Check the token in your action using the same CSRF token id.
|
||||
*
|
||||
* <code>
|
||||
* $csrfProvider = $this->get('security.csrf.token_generator');
|
||||
* // $csrfProvider being an instance of Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface
|
||||
* if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) {
|
||||
* throw new \RuntimeException('CSRF attack detected.');
|
||||
* }
|
||||
|
@ -21,10 +21,8 @@ class SubRequestController implements ContainerAwareInterface
|
||||
{
|
||||
use ContainerAwareTrait;
|
||||
|
||||
public function indexAction()
|
||||
public function indexAction($handler)
|
||||
{
|
||||
$handler = $this->container->get('fragment.handler');
|
||||
|
||||
$errorUrl = $this->generateUrl('subrequest_fragment_error', array('_locale' => 'fr', '_format' => 'json'));
|
||||
$altUrl = $this->generateUrl('subrequest_fragment', array('_locale' => 'fr', '_format' => 'json'));
|
||||
|
||||
|
@ -1,2 +1,7 @@
|
||||
imports:
|
||||
- { resource: ./../config/default.yml }
|
||||
|
||||
services:
|
||||
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestController:
|
||||
tags:
|
||||
- { name: controller.service_arguments, action: indexAction, argument: handler, id: fragment.handler }
|
||||
|
@ -17,7 +17,8 @@ use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
|
||||
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class WebProfilerExtensionTest extends TestCase
|
||||
{
|
||||
@ -51,6 +52,7 @@ class WebProfilerExtensionTest extends TestCase
|
||||
$this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock();
|
||||
|
||||
$this->container = new ContainerBuilder();
|
||||
$this->container->register('event_dispatcher', EventDispatcher::class);
|
||||
$this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface'));
|
||||
$this->container->register('twig', 'Twig\Environment');
|
||||
$this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array());
|
||||
@ -66,6 +68,7 @@ class WebProfilerExtensionTest extends TestCase
|
||||
->addArgument(new Definition($this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface')));
|
||||
$this->container->setParameter('data_collector.templates', array());
|
||||
$this->container->set('kernel', $this->kernel);
|
||||
$this->container->addCompilerPass(new RegisterListenersPass());
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
@ -88,7 +91,7 @@ class WebProfilerExtensionTest extends TestCase
|
||||
|
||||
$this->assertFalse($this->container->has('web_profiler.debug_toolbar'));
|
||||
|
||||
$this->assertSaneContainer($this->getDumpedContainer());
|
||||
$this->assertSaneContainer($this->getCompiledContainer());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,7 +104,7 @@ class WebProfilerExtensionTest extends TestCase
|
||||
|
||||
$this->assertSame($listenerInjected, $this->container->has('web_profiler.debug_toolbar'));
|
||||
|
||||
$this->assertSaneContainer($this->getDumpedContainer(), '', array('web_profiler.csp.handler'));
|
||||
$this->assertSaneContainer($this->getCompiledContainer(), '', array('web_profiler.csp.handler'));
|
||||
|
||||
if ($listenerInjected) {
|
||||
$this->assertSame($listenerEnabled, $this->container->get('web_profiler.debug_toolbar')->isEnabled());
|
||||
@ -118,19 +121,11 @@ class WebProfilerExtensionTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
private function getDumpedContainer()
|
||||
private function getCompiledContainer()
|
||||
{
|
||||
static $i = 0;
|
||||
$class = 'WebProfilerExtensionTestContainer'.$i++;
|
||||
|
||||
$this->container->compile();
|
||||
$this->container->set('kernel', $this->kernel);
|
||||
|
||||
$dumper = new PhpDumper($this->container);
|
||||
eval('?>'.$dumper->dump(array('class' => $class)));
|
||||
|
||||
$container = new $class();
|
||||
$container->set('kernel', $this->kernel);
|
||||
|
||||
return $container;
|
||||
return $this->container;
|
||||
}
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ interface FormRendererInterface
|
||||
* Check the token in your action using the same token ID.
|
||||
*
|
||||
* <code>
|
||||
* $csrfProvider = $this->get('security.csrf.token_generator');
|
||||
* // $csrfProvider being an instance of Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface
|
||||
* if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) {
|
||||
* throw new \RuntimeException('CSRF attack detected.');
|
||||
* }
|
||||
|
Reference in New Issue
Block a user