*/
-class Logger extends BaseLogger implements DebugLoggerInterface
+class Logger extends BaseLogger implements DebugLoggerInterface, ResetInterface
{
/**
* {@inheritdoc}
@@ -56,6 +57,14 @@ public function clear()
}
}
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->clear();
+ }
+
/**
* Returns a DebugLoggerInterface instance if one is registered with this logger.
*
diff --git a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php
index a6998517e7003..13f8a2de3e48a 100644
--- a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php
+++ b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php
@@ -15,8 +15,9 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
+use Symfony\Contracts\Service\ResetInterface;
-class DebugProcessor implements DebugLoggerInterface
+class DebugProcessor implements DebugLoggerInterface, ResetInterface
{
private $records = array();
private $errorCount = array();
@@ -91,4 +92,12 @@ public function clear()
$this->records = array();
$this->errorCount = array();
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function reset()
+ {
+ $this->clear();
+ }
}
diff --git a/src/Symfony/Bridge/Monolog/Processor/ProcessorInterface.php b/src/Symfony/Bridge/Monolog/Processor/ProcessorInterface.php
new file mode 100644
index 0000000000000..3b470992fc2f8
--- /dev/null
+++ b/src/Symfony/Bridge/Monolog/Processor/ProcessorInterface.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bridge\Monolog\Processor;
+
+/**
+ * An optional interface to allow autoconfiguration of Monolog processors.
+ *
+ * @author Nicolas Grekas
+ */
+interface ProcessorInterface
+{
+ /**
+ * @return array The processed records
+ */
+ public function __invoke(array $records);
+}
diff --git a/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php
index 11547be22b2ee..87c52c6a0d39f 100644
--- a/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php
+++ b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php
@@ -18,7 +18,7 @@
*
* @author Dany Maillard
*/
-class TokenProcessor
+class TokenProcessor implements ProcessorInterface
{
private $tokenStorage;
diff --git a/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php b/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php
index 9c32e756c514e..671e7e57286af 100644
--- a/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php
+++ b/src/Symfony/Bridge/Monolog/Processor/WebProcessor.php
@@ -21,7 +21,7 @@
*
* @author Jordi Boggiano
*/
-class WebProcessor extends BaseWebProcessor implements EventSubscriberInterface
+class WebProcessor extends BaseWebProcessor implements EventSubscriberInterface, ProcessorInterface
{
public function __construct(array $extraFields = null)
{
diff --git a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php
index 92b319f13a989..b22299c11bf7c 100644
--- a/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php
+++ b/src/Symfony/Bridge/Monolog/Tests/Handler/ConsoleHandlerTest.php
@@ -180,19 +180,19 @@ public function testLogsFromListeners()
$dispatcher = new EventDispatcher();
$dispatcher->addListener(ConsoleEvents::COMMAND, function () use ($logger) {
- $logger->addInfo('Before command message.');
+ $logger->info('Before command message.');
});
$dispatcher->addListener(ConsoleEvents::TERMINATE, function () use ($logger) {
- $logger->addInfo('Before terminate message.');
+ $logger->info('Before terminate message.');
});
$dispatcher->addSubscriber($handler);
$dispatcher->addListener(ConsoleEvents::COMMAND, function () use ($logger) {
- $logger->addInfo('After command message.');
+ $logger->info('After command message.');
});
$dispatcher->addListener(ConsoleEvents::TERMINATE, function () use ($logger) {
- $logger->addInfo('After terminate message.');
+ $logger->info('After terminate message.');
});
$event = new ConsoleCommandEvent(new Command('foo'), $this->getMockBuilder('Symfony\Component\Console\Input\InputInterface')->getMock(), $output);
diff --git a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php
index 193cde6728eca..46156adbd8b79 100644
--- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php
+++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php
@@ -24,7 +24,7 @@ public function testGetLogsWithoutDebugProcessor()
$handler = new TestHandler();
$logger = new Logger(__METHOD__, array($handler));
- $this->assertTrue($logger->error('error message'));
+ $logger->error('error message');
$this->assertSame(array(), $logger->getLogs());
}
@@ -33,7 +33,7 @@ public function testCountErrorsWithoutDebugProcessor()
$handler = new TestHandler();
$logger = new Logger(__METHOD__, array($handler));
- $this->assertTrue($logger->error('error message'));
+ $logger->error('error message');
$this->assertSame(0, $logger->countErrors());
}
@@ -43,7 +43,7 @@ public function testGetLogsWithDebugProcessor()
$processor = new DebugProcessor();
$logger = new Logger(__METHOD__, array($handler), array($processor));
- $this->assertTrue($logger->error('error message'));
+ $logger->error('error message');
$this->assertCount(1, $logger->getLogs());
}
@@ -53,15 +53,15 @@ public function testCountErrorsWithDebugProcessor()
$processor = new DebugProcessor();
$logger = new Logger(__METHOD__, array($handler), array($processor));
- $this->assertTrue($logger->debug('test message'));
- $this->assertTrue($logger->info('test message'));
- $this->assertTrue($logger->notice('test message'));
- $this->assertTrue($logger->warning('test message'));
+ $logger->debug('test message');
+ $logger->info('test message');
+ $logger->notice('test message');
+ $logger->warning('test message');
- $this->assertTrue($logger->error('test message'));
- $this->assertTrue($logger->critical('test message'));
- $this->assertTrue($logger->alert('test message'));
- $this->assertTrue($logger->emergency('test message'));
+ $logger->error('test message');
+ $logger->critical('test message');
+ $logger->alert('test message');
+ $logger->emergency('test message');
$this->assertSame(4, $logger->countErrors());
}
@@ -72,7 +72,7 @@ public function testGetLogsWithDebugProcessor2()
$logger = new Logger('test', array($handler));
$logger->pushProcessor(new DebugProcessor());
- $logger->addInfo('test');
+ $logger->info('test');
$this->assertCount(1, $logger->getLogs());
list($record) = $logger->getLogs();
@@ -101,7 +101,7 @@ public function testClear()
$logger = new Logger('test', array($handler));
$logger->pushProcessor(new DebugProcessor());
- $logger->addInfo('test');
+ $logger->info('test');
$logger->clear();
$this->assertEmpty($logger->getLogs());
diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json
index a4d3e984100c9..535c2d23bcea3 100644
--- a/src/Symfony/Bridge/Monolog/composer.json
+++ b/src/Symfony/Bridge/Monolog/composer.json
@@ -18,6 +18,7 @@
"require": {
"php": "^7.1.3",
"monolog/monolog": "~1.19",
+ "symfony/contracts": "^1.0",
"symfony/http-kernel": "~3.4|~4.0"
},
"require-dev": {
@@ -44,7 +45,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.2-dev"
}
}
}
diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json
index 7338fca00db74..4d72603eb452f 100644
--- a/src/Symfony/Bridge/PhpUnit/composer.json
+++ b/src/Symfony/Bridge/PhpUnit/composer.json
@@ -40,7 +40,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.2-dev"
},
"thanks": {
"name": "phpunit/phpunit",
diff --git a/src/Symfony/Bridge/ProxyManager/CHANGELOG.md b/src/Symfony/Bridge/ProxyManager/CHANGELOG.md
index 56c8b20e28272..3435a4a186494 100644
--- a/src/Symfony/Bridge/ProxyManager/CHANGELOG.md
+++ b/src/Symfony/Bridge/ProxyManager/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+4.2.0
+-----
+
+ * allowed creating lazy-proxies from interfaces
+
3.3.0
-----
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactory.php
similarity index 85%
rename from src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php
rename to src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactory.php
index a643f33710dd2..caea93ac5d9f4 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactory.php
@@ -18,14 +18,14 @@
/**
* @internal
*/
-class LazyLoadingValueHolderFactoryV2 extends BaseFactory
+class LazyLoadingValueHolderFactory extends BaseFactory
{
private $generator;
/**
* {@inheritdoc}
*/
- protected function getGenerator(): ProxyGeneratorInterface
+ public function getGenerator(): ProxyGeneratorInterface
{
return $this->generator ?: $this->generator = new LazyLoadingValueHolderGenerator();
}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php
deleted file mode 100644
index 3298b84d46278..0000000000000
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php
+++ /dev/null
@@ -1,31 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator;
-
-use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory;
-use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator;
-
-/**
- * @internal
- */
-class LazyLoadingValueHolderFactoryV1 extends BaseFactory
-{
- private $generatorV1;
-
- /**
- * {@inheritdoc}
- */
- protected function getGenerator()
- {
- return $this->generatorV1 ?: $this->generatorV1 = new LazyLoadingValueHolderGenerator();
- }
-}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
index 7d083a6981e25..cc68d65058839 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php
@@ -12,7 +12,6 @@
namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator;
use ProxyManager\Configuration;
-use ProxyManager\Factory\LazyLoadingValueHolderFactory;
use ProxyManager\GeneratorStrategy\EvaluatingGeneratorStrategy;
use ProxyManager\Proxy\LazyLoadingInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -26,9 +25,6 @@
*/
class RuntimeInstantiator implements InstantiatorInterface
{
- /**
- * @var LazyLoadingValueHolderFactory
- */
private $factory;
public function __construct()
@@ -36,11 +32,7 @@ public function __construct()
$config = new Configuration();
$config->setGeneratorStrategy(new EvaluatingGeneratorStrategy());
- if (method_exists('ProxyManager\Version', 'getVersion')) {
- $this->factory = new LazyLoadingValueHolderFactoryV2($config);
- } else {
- $this->factory = new LazyLoadingValueHolderFactoryV1($config);
- }
+ $this->factory = new LazyLoadingValueHolderFactory($config);
}
/**
@@ -49,7 +41,7 @@ public function __construct()
public function instantiateProxy(ContainerInterface $container, Definition $definition, $id, $realInstantiator)
{
return $this->factory->createProxy(
- $definition->getClass(),
+ $this->factory->getGenerator()->getProxifiedClass($definition),
function (&$wrappedInstance, LazyLoadingInterface $proxy) use ($realInstantiator) {
$wrappedInstance = \call_user_func($realInstantiator);
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php
index 1d9432f622b41..356fd44cda454 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php
@@ -12,6 +12,7 @@
namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper;
use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator as BaseGenerator;
+use Symfony\Component\DependencyInjection\Definition;
use Zend\Code\Generator\ClassGenerator;
/**
@@ -19,6 +20,13 @@
*/
class LazyLoadingValueHolderGenerator extends BaseGenerator
{
+ private $fluentSafe = false;
+
+ public function setFluentSafe(bool $fluentSafe)
+ {
+ $this->fluentSafe = $fluentSafe;
+ }
+
/**
* {@inheritdoc}
*/
@@ -26,6 +34,52 @@ public function generate(\ReflectionClass $originalClass, ClassGenerator $classG
{
parent::generate($originalClass, $classGenerator);
+ foreach ($classGenerator->getMethods() as $method) {
+ $body = preg_replace(
+ '/(\$this->initializer[0-9a-f]++) && \1->__invoke\(\$this->(valueHolder[0-9a-f]++), (.*?), \1\);/',
+ '$1 && ($1->__invoke(\$$2, $3, $1) || 1) && $this->$2 = \$$2;',
+ $method->getBody()
+ );
+ $body = str_replace('(new \ReflectionClass(get_class()))', '$reflection', $body);
+
+ if ($originalClass->isInterface()) {
+ $body = str_replace('get_parent_class($this)', var_export($originalClass->name, true), $body);
+ $body = preg_replace_callback('/\n\n\$realInstanceReflection = [^{]++\{([^}]++)\}\n\n.*/s', function ($m) {
+ $r = '';
+ foreach (explode("\n", $m[1]) as $line) {
+ $r .= "\n".substr($line, 4);
+ if (0 === strpos($line, ' return ')) {
+ break;
+ }
+ }
+
+ return $r;
+ }, $body);
+ }
+
+ if ($this->fluentSafe) {
+ $indent = $method->getIndentation();
+ $method->setIndentation('');
+ $code = $method->generate();
+ if (null !== $docBlock = $method->getDocBlock()) {
+ $code = substr($code, \strlen($docBlock->generate()));
+ }
+ $refAmp = (strpos($code, '&') ?: \PHP_INT_MAX) <= strpos($code, '(') ? '&' : '';
+ $body = preg_replace(
+ '/\nreturn (\$this->valueHolder[0-9a-f]++)(->[^;]++);$/',
+ "\nif ($1 === \$returnValue = {$refAmp}$1$2) {\n \$returnValue = \$this;\n}\n\nreturn \$returnValue;",
+ $body
+ );
+ $method->setIndentation($indent);
+ }
+
+ if (0 === strpos($originalClass->getFilename(), __FILE__)) {
+ $body = str_replace(var_export($originalClass->name, true), '__CLASS__', $body);
+ }
+
+ $method->setBody($body);
+ }
+
if ($classGenerator->hasMethod('__destruct')) {
$destructor = $classGenerator->getMethod('__destruct');
$body = $destructor->getBody();
@@ -37,5 +91,53 @@ public function generate(\ReflectionClass $originalClass, ClassGenerator $classG
$destructor->setBody($newBody);
}
+
+ if (0 === strpos($originalClass->getFilename(), __FILE__)) {
+ $interfaces = $classGenerator->getImplementedInterfaces();
+ array_pop($interfaces);
+ $classGenerator->setImplementedInterfaces(array_merge($interfaces, $originalClass->getInterfaceNames()));
+ }
+ }
+
+ public function getProxifiedClass(Definition $definition): ?string
+ {
+ if (!$definition->hasTag('proxy')) {
+ return \class_exists($class = $definition->getClass()) || \interface_exists($class) ? $class : null;
+ }
+ if (!$definition->isLazy()) {
+ throw new \InvalidArgumentException(sprintf('Invalid definition for service of class "%s": setting the "proxy" tag on a service requires it to be "lazy".', $definition->getClass()));
+ }
+ $tags = $definition->getTag('proxy');
+ if (!isset($tags[0]['interface'])) {
+ throw new \InvalidArgumentException(sprintf('Invalid definition for service of class "%s": the "interface" attribute is missing on the "proxy" tag.', $definition->getClass()));
+ }
+ if (1 === \count($tags)) {
+ return \class_exists($tags[0]['interface']) || \interface_exists($tags[0]['interface']) ? $tags[0]['interface'] : null;
+ }
+
+ $proxyInterface = 'LazyProxy';
+ $interfaces = '';
+ foreach ($tags as $tag) {
+ if (!isset($tag['interface'])) {
+ throw new \InvalidArgumentException(sprintf('Invalid definition for service of class "%s": the "interface" attribute is missing on a "proxy" tag.', $definition->getClass()));
+ }
+ if (!\interface_exists($tag['interface'])) {
+ throw new \InvalidArgumentException(sprintf('Invalid definition for service of class "%s": several "proxy" tags found but "%s" is not an interface.', $definition->getClass(), $tag['interface']));
+ }
+
+ $proxyInterface .= '\\'.$tag['interface'];
+ $interfaces .= ', \\'.$tag['interface'];
+ }
+
+ if (!\interface_exists($proxyInterface)) {
+ $i = strrpos($proxyInterface, '\\');
+ $namespace = substr($proxyInterface, 0, $i);
+ $interface = substr($proxyInterface, 1 + $i);
+ $interfaces = substr($interfaces, 2);
+
+ eval("namespace {$namespace}; interface {$interface} extends {$interfaces} {}");
+ }
+
+ return $proxyInterface;
}
}
diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
index 18da9118a2226..208639a4b1ec3 100644
--- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
+++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php
@@ -14,7 +14,6 @@
use ProxyManager\Generator\ClassGenerator;
use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy;
use ProxyManager\Version;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface;
@@ -43,7 +42,7 @@ public function __construct(string $salt = '')
*/
public function isProxyCandidate(Definition $definition)
{
- return $definition->isLazy() && ($class = $definition->getClass()) && class_exists($class);
+ return ($definition->isLazy() || $definition->hasTag('proxy')) && $this->proxyGenerator->getProxifiedClass($definition);
}
/**
@@ -54,7 +53,7 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode =
$instantiation = 'return';
if ($definition->isShared()) {
- $instantiation .= sprintf(' $this->%s[\'%s\'] =', \method_exists(ContainerBuilder::class, 'addClassResource') || ($definition->isPublic() && !$definition->isPrivate()) ? 'services' : 'privates', $id);
+ $instantiation .= sprintf(' $this->%s[\'%s\'] =', $definition->isPublic() && !$definition->isPrivate() ? 'services' : 'privates', $id);
}
if (null === $factoryCode) {
@@ -63,14 +62,10 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode =
$proxyClass = $this->getProxyClassName($definition);
- $hasStaticConstructor = $this->generateProxyClass($definition)->hasMethod('staticProxyConstructor');
-
- $constructorCall = sprintf($hasStaticConstructor ? '%s::staticProxyConstructor' : 'new %s', '\\'.$proxyClass);
-
return <<createProxy('$proxyClass', function () {
- return $constructorCall(function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) {
+ return \\$proxyClass::staticProxyConstructor(function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) {
\$wrappedInstance = $factoryCode;
\$proxy->setProxyInitializer(null);
@@ -91,12 +86,6 @@ public function getProxyCode(Definition $definition)
{
$code = $this->classGenerator->generate($this->generateProxyClass($definition));
- $code = preg_replace(
- '/(\$this->initializer[0-9a-f]++) && \1->__invoke\(\$this->(valueHolder[0-9a-f]++), (.*?), \1\);/',
- '$1 && ($1->__invoke(\$$2, $3, $1) || 1) && $this->$2 = \$$2;',
- $code
- );
-
if (version_compare(self::getProxyManagerVersion(), '2.2', '<')) {
$code = preg_replace(
'/((?:\$(?:this|initializer|instance)->)?(?:publicProperties|initializer|valueHolder))[0-9a-f]++/',
@@ -122,20 +111,26 @@ private static function getProxyManagerVersion(): string
*/
private function getProxyClassName(Definition $definition): string
{
- return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.$this->getIdentifierSuffix($definition);
+ $class = $this->proxyGenerator->getProxifiedClass($definition);
+
+ return preg_replace('/^.*\\\\/', '', $class).'_'.$this->getIdentifierSuffix($definition);
}
private function generateProxyClass(Definition $definition): ClassGenerator
{
$generatedClass = new ClassGenerator($this->getProxyClassName($definition));
+ $class = $this->proxyGenerator->getProxifiedClass($definition);
- $this->proxyGenerator->generate(new \ReflectionClass($definition->getClass()), $generatedClass);
+ $this->proxyGenerator->setFluentSafe($definition->hasTag('proxy'));
+ $this->proxyGenerator->generate(new \ReflectionClass($class), $generatedClass);
return $generatedClass;
}
private function getIdentifierSuffix(Definition $definition): string
{
- return substr(hash('sha256', $definition->getClass().$this->salt), -7);
+ $class = $this->proxyGenerator->getProxifiedClass($definition);
+
+ return substr(hash('sha256', $class.$this->salt), -7);
}
}
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-factory.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-factory.php
new file mode 100644
index 0000000000000..648eb36d4b598
--- /dev/null
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-factory.php
@@ -0,0 +1,31 @@
+privates['foo'] = $this->createProxy('SunnyInterface_1eff735', function () {
+ return \SunnyInterface_1eff735::staticProxyConstructor(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {
+ $wrappedInstance = $this->getFooService(false);
+
+ $proxy->setProxyInitializer(null);
+
+ return true;
+ });
+ });
+ }
+
+ return new Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper\DummyClass();
+ }
+
+ protected function createProxy($class, \Closure $factory)
+ {
+ $this->proxyClass = $class;
+
+ return $factory();
+ }
+};
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-implem.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-implem.php
new file mode 100644
index 0000000000000..1b5ea69c907e7
--- /dev/null
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/Fixtures/proxy-implem.php
@@ -0,0 +1,165 @@
+initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, 'dummy', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ if ($this->valueHolder1eff735 === $returnValue = $this->valueHolder1eff735->dummy()) {
+ $returnValue = $this;
+ }
+
+ return $returnValue;
+ }
+
+ public function & dummyRef()
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, 'dummyRef', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ if ($this->valueHolder1eff735 === $returnValue = &$this->valueHolder1eff735->dummyRef()) {
+ $returnValue = $this;
+ }
+
+ return $returnValue;
+ }
+
+ public function sunny()
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, 'sunny', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ if ($this->valueHolder1eff735 === $returnValue = $this->valueHolder1eff735->sunny()) {
+ $returnValue = $this;
+ }
+
+ return $returnValue;
+ }
+
+ public static function staticProxyConstructor($initializer)
+ {
+ static $reflection;
+
+ $reflection = $reflection ?: $reflection = new \ReflectionClass(__CLASS__);
+ $instance = $reflection->newInstanceWithoutConstructor();
+
+ $instance->initializer1eff735 = $initializer;
+
+ return $instance;
+ }
+
+ public function __construct()
+ {
+ static $reflection;
+
+ if (! $this->valueHolder1eff735) {
+ $reflection = $reflection ?: new \ReflectionClass(__CLASS__);
+ $this->valueHolder1eff735 = $reflection->newInstanceWithoutConstructor();
+ }
+ }
+
+ public function & __get($name)
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__get', ['name' => $name], $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ if (isset(self::$publicProperties1eff735[$name])) {
+ return $this->valueHolder1eff735->$name;
+ }
+
+ $targetObject = $this->valueHolder1eff735;
+
+ $backtrace = debug_backtrace(false);
+ trigger_error(
+ sprintf(
+ 'Undefined property: %s::$%s in %s on line %s',
+ __CLASS__,
+ $name,
+ $backtrace[0]['file'],
+ $backtrace[0]['line']
+ ),
+ \E_USER_NOTICE
+ );
+ return $targetObject->$name;
+ }
+
+ public function __set($name, $value)
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__set', array('name' => $name, 'value' => $value), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ $targetObject = $this->valueHolder1eff735;
+
+ return $targetObject->$name = $value;
+ }
+
+ public function __isset($name)
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__isset', array('name' => $name), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ $targetObject = $this->valueHolder1eff735;
+
+ return isset($targetObject->$name);
+ }
+
+ public function __unset($name)
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__unset', array('name' => $name), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ $targetObject = $this->valueHolder1eff735;
+
+ unset($targetObject->$name);
+return;
+ }
+
+ public function __clone()
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__clone', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ $this->valueHolder1eff735 = clone $this->valueHolder1eff735;
+ }
+
+ public function __sleep()
+ {
+ $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, '__sleep', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+
+ return array('valueHolder1eff735');
+ }
+
+ public function __wakeup()
+ {
+ }
+
+ public function setProxyInitializer(\Closure $initializer = null)
+ {
+ $this->initializer1eff735 = $initializer;
+ }
+
+ public function getProxyInitializer()
+ {
+ return $this->initializer1eff735;
+ }
+
+ public function initializeProxy() : bool
+ {
+ return $this->initializer1eff735 && ($this->initializer1eff735->__invoke($valueHolder1eff735, $this, 'initializeProxy', array(), $this->initializer1eff735) || 1) && $this->valueHolder1eff735 = $valueHolder1eff735;
+ }
+
+ public function isProxyInitialized() : bool
+ {
+ return null !== $this->valueHolder1eff735;
+ }
+
+ public function getWrappedValueHolderValue()
+ {
+ return $this->valueHolder1eff735;
+ }
+
+
+}
diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
index e12b25fcb02f8..b1dc1cf66a2ea 100644
--- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
+++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php
@@ -13,7 +13,6 @@
use PHPUnit\Framework\TestCase;
use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
/**
@@ -99,7 +98,7 @@ public function getPrivatePublicDefinitions()
array(
(new Definition(__CLASS__))
->setPublic(false),
- \method_exists(ContainerBuilder::class, 'addClassResource') ? 'services' : 'privates',
+ 'privates',
),
array(
(new Definition(__CLASS__))
@@ -120,6 +119,61 @@ public function testGetProxyFactoryCodeWithoutCustomMethod()
$this->dumper->getProxyFactoryCode($definition, 'foo');
}
+ public function testGetProxyFactoryCodeForInterface()
+ {
+ $class = DummyClass::class;
+ $definition = new Definition($class);
+
+ $definition->setLazy(true);
+ $definition->addTag('proxy', array('interface' => DummyInterface::class));
+ $definition->addTag('proxy', array('interface' => SunnyInterface::class));
+
+ $implem = "dumper->getProxyCode($definition);
+ $factory = $this->dumper->getProxyFactoryCode($definition, 'foo', '$this->getFooService(false)');
+ $factory = <<proxyClass = \$class;
+
+ return \$factory();
+ }
+};
+
+EOPHP;
+
+ $implem = preg_replace('#\n /\*\*.*?\*/#s', '', $implem);
+ $implem = str_replace('getWrappedValueHolderValue() : ?object', 'getWrappedValueHolderValue()', $implem);
+ $implem = str_replace("array(\n \n );", "[\n \n ];", $implem);
+ $this->assertStringEqualsFile(__DIR__.'/Fixtures/proxy-implem.php', $implem);
+ $this->assertStringEqualsFile(__DIR__.'/Fixtures/proxy-factory.php', $factory);
+
+ require_once __DIR__.'/Fixtures/proxy-implem.php';
+ $factory = require __DIR__.'/Fixtures/proxy-factory.php';
+
+ $foo = $factory->getFooService();
+
+ $this->assertInstanceof($factory->proxyClass, $foo);
+ $this->assertInstanceof(DummyInterface::class, $foo);
+ $this->assertInstanceof(SunnyInterface::class, $foo);
+ $this->assertNotInstanceof(DummyClass::class, $foo);
+ $this->assertSame($foo, $foo->dummy());
+
+ $foo->dynamicProp = 123;
+ $this->assertSame(123, @$foo->dynamicProp);
+ }
+
/**
* @return array
*/
@@ -142,3 +196,34 @@ function ($definition) {
return $definitions;
}
}
+
+final class DummyClass implements DummyInterface, SunnyInterface
+{
+ public function dummy()
+ {
+ return $this;
+ }
+
+ public function sunny()
+ {
+ }
+
+ public function &dummyRef()
+ {
+ return $this->ref;
+ }
+}
+
+interface DummyInterface
+{
+ public function dummy();
+
+ public function &dummyRef();
+}
+
+interface SunnyInterface
+{
+ public function dummy();
+
+ public function sunny();
+}
diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json
index 90f000c828618..16b95e8318104 100644
--- a/src/Symfony/Bridge/ProxyManager/composer.json
+++ b/src/Symfony/Bridge/ProxyManager/composer.json
@@ -17,8 +17,8 @@
],
"require": {
"php": "^7.1.3",
- "symfony/dependency-injection": "~3.4|~4.0",
- "ocramius/proxy-manager": "~0.4|~1.0|~2.0"
+ "symfony/dependency-injection": "~4.0",
+ "ocramius/proxy-manager": "~2.1"
},
"require-dev": {
"symfony/config": "~3.4|~4.0"
@@ -32,7 +32,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.2-dev"
}
}
}
diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md
index fcdb5e2756086..fd0a0fa54b4fc 100644
--- a/src/Symfony/Bridge/Twig/CHANGELOG.md
+++ b/src/Symfony/Bridge/Twig/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+4.2.0
+-----
+
+* add bundle name suggestion on wrongly overridden templates paths
+
4.1.0
-----
diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
index 6f40182405369..82d7b8523ab1e 100644
--- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php
+++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php
@@ -31,13 +31,19 @@ class DebugCommand extends Command
private $twig;
private $projectDir;
+ private $bundlesMetadata;
+ private $twigDefaultPath;
+ private $rootDir;
- public function __construct(Environment $twig, string $projectDir = null)
+ public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = array(), string $twigDefaultPath = null, string $rootDir = null)
{
parent::__construct();
$this->twig = $twig;
$this->projectDir = $projectDir;
+ $this->bundlesMetadata = $bundlesMetadata;
+ $this->twigDefaultPath = $twigDefaultPath;
+ $this->rootDir = $rootDir;
}
protected function configure()
@@ -82,6 +88,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$data['tests'] = array_keys($data['tests']);
$data['loader_paths'] = $this->getLoaderPaths();
+ if ($wrongBundles = $this->findWrongBundleOverrides()) {
+ $data['warnings'] = $this->buildWarningMessages($wrongBundles);
+ }
+
$io->writeln(json_encode($data));
return 0;
@@ -131,6 +141,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$io->section('Loader Paths');
$io->table(array('Namespace', 'Paths'), $rows);
+ $messages = $this->buildWarningMessages($this->findWrongBundleOverrides());
+ foreach ($messages as $message) {
+ $io->warning($message);
+ }
return 0;
}
@@ -250,4 +264,85 @@ private function getPrettyMetadata($type, $entity)
return $meta ? '('.implode(', ', $meta).')' : '';
}
}
+
+ private function findWrongBundleOverrides(): array
+ {
+ $alternatives = array();
+ $bundleNames = array();
+
+ if ($this->rootDir && $this->projectDir) {
+ $folders = glob($this->rootDir.'/Resources/*/views', GLOB_ONLYDIR);
+ $relativePath = ltrim(substr($this->rootDir.'/Resources/', \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
+ $bundleNames = array_reduce(
+ $folders,
+ function ($carry, $absolutePath) use ($relativePath) {
+ if (0 === strpos($absolutePath, $this->projectDir)) {
+ $name = basename(\dirname($absolutePath));
+ $path = $relativePath.$name;
+ $carry[$name] = $path;
+ }
+
+ return $carry;
+ },
+ $bundleNames
+ );
+ }
+
+ if ($this->twigDefaultPath && $this->projectDir) {
+ $folders = glob($this->twigDefaultPath.'/bundles/*', GLOB_ONLYDIR);
+ $relativePath = ltrim(substr($this->twigDefaultPath.'/bundles', \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
+ $bundleNames = array_reduce(
+ $folders,
+ function ($carry, $absolutePath) use ($relativePath) {
+ if (0 === strpos($absolutePath, $this->projectDir)) {
+ $path = ltrim(substr($absolutePath, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
+ $name = ltrim(substr($path, \strlen($relativePath)), \DIRECTORY_SEPARATOR);
+ $carry[$name] = $path;
+ }
+
+ return $carry;
+ },
+ $bundleNames
+ );
+ }
+
+ if (\count($bundleNames)) {
+ $notFoundBundles = array_diff_key($bundleNames, $this->bundlesMetadata);
+ if (\count($notFoundBundles)) {
+ $alternatives = array();
+ foreach ($notFoundBundles as $notFoundBundle => $path) {
+ $alternatives[$path] = array();
+ foreach ($this->bundlesMetadata as $name => $bundle) {
+ $lev = levenshtein($notFoundBundle, $name);
+ if ($lev <= \strlen($notFoundBundle) / 3 || false !== strpos($name, $notFoundBundle)) {
+ $alternatives[$path][] = $name;
+ }
+ }
+ }
+ }
+ }
+
+ return $alternatives;
+ }
+
+ private function buildWarningMessages(array $wrongBundles): array
+ {
+ $messages = array();
+ foreach ($wrongBundles as $path => $alternatives) {
+ $message = sprintf('Path "%s" not matching any bundle found', $path);
+ if ($alternatives) {
+ if (1 === \count($alternatives)) {
+ $message .= sprintf(", did you mean \"%s\"?\n", $alternatives[0]);
+ } else {
+ $message .= ", did you mean one of these:\n";
+ foreach ($alternatives as $bundle) {
+ $message .= sprintf(" - %s\n", $bundle);
+ }
+ }
+ }
+ $messages[] = trim($message);
+ }
+
+ return $messages;
+ }
}
diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php
index f84eaeb7e72e9..cd00f44d57b00 100644
--- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php
@@ -25,17 +25,19 @@ class CodeExtension extends AbstractExtension
private $fileLinkFormat;
private $rootDir;
private $charset;
+ private $projectDir;
/**
* @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
* @param string $rootDir The project root directory
* @param string $charset The charset
*/
- public function __construct($fileLinkFormat, string $rootDir, string $charset)
+ public function __construct($fileLinkFormat, string $rootDir, string $charset, string $projectDir = null)
{
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
$this->rootDir = str_replace('/', \DIRECTORY_SEPARATOR, \dirname($rootDir)).\DIRECTORY_SEPARATOR;
$this->charset = $charset;
+ $this->projectDir = $projectDir;
}
/**
@@ -53,6 +55,7 @@ public function getFilters()
new TwigFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))),
new TwigFilter('format_log_message', array($this, 'formatLogMessage'), array('is_safe' => array('html'))),
new TwigFilter('file_link', array($this, 'getFileLink')),
+ new TwigFilter('file_relative', array($this, 'getFileRelative')),
);
}
@@ -209,6 +212,15 @@ public function getFileLink($file, $line)
return false;
}
+ public function getFileRelative(string $file): ?string
+ {
+ if (null !== $this->projectDir && 0 === strpos($file, $this->projectDir)) {
+ return ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
+ }
+
+ return null;
+ }
+
public function formatFileFromText($text)
{
return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) {
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
index 0094a1cde1261..02c86fddc2246 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -398,7 +398,7 @@
{# Support #}
{%- block form_rows -%}
- {% for child in form %}
+ {% for child in form if not child.rendered %}
{{- form_row(child) -}}
{% endfor %}
{%- endblock form_rows -%}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
index 336991c6ca9f2..c152ba6d60137 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/CodeExtensionTest.php
@@ -23,6 +23,11 @@ public function testFormatFile()
$this->assertEquals($expected, $this->getExtension()->formatFile(__FILE__, 25));
}
+ public function testFileRelative()
+ {
+ $this->assertEquals('CodeExtensionTest.php', $this->getExtension()->getFileRelative(__FILE__));
+ }
+
/**
* @dataProvider getClassNameProvider
*/
@@ -64,6 +69,6 @@ public function testGetName()
protected function getExtension()
{
- return new CodeExtension(new FileLinkFormatter('proto://%f#&line=%l&'.substr(__FILE__, 0, 5).'>foobar'), '/root', 'UTF-8');
+ return new CodeExtension(new FileLinkFormatter('proto://%f#&line=%l&'.substr(__FILE__, 0, 5).'>foobar'), '/root', 'UTF-8', __DIR__);
}
}
diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json
index 839636282c78a..aaf5d775273f6 100644
--- a/src/Symfony/Bridge/Twig/composer.json
+++ b/src/Symfony/Bridge/Twig/composer.json
@@ -68,7 +68,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.2-dev"
}
}
}
diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php
index cbb27c479fd01..436a95c50b6f7 100644
--- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php
@@ -26,10 +26,9 @@ class Configuration implements ConfigurationInterface
*/
public function getConfigTreeBuilder()
{
- $treeBuilder = new TreeBuilder();
- $rootNode = $treeBuilder->root('debug');
+ $treeBuilder = new TreeBuilder('debug');
- $rootNode
+ $treeBuilder->getRootNode()
->children()
->integerNode('max_items')
->info('Max number of displayed items past the first level, -1 means no limit')
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index e909b45814f7f..535d0edfa8050 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -23,11 +23,12 @@
"symfony/var-dumper": "^4.1.1"
},
"require-dev": {
- "symfony/config": "~3.4|~4.0",
+ "symfony/config": "~4.2",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/web-profiler-bundle": "~3.4|~4.0"
},
"conflict": {
+ "symfony/config": "<4.2",
"symfony/dependency-injection": "<3.4"
},
"suggest": {
@@ -43,7 +44,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "4.1-dev"
+ "dev-master": "4.2-dev"
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index b03567d68e35a..e285ebf8a13cb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -1,6 +1,14 @@
CHANGELOG
=========
+4.2.0
+-----
+
+ * Allowed configuring taggable cache pools via a new `framework.cache.pools.tags` option (bool|service-id)
+ * Allowed configuring PDO-based cache pools via a new `cache.adapter.pdo` abstract service
+ * Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead
+ * Deprecated processing of services tagged `security.expression_language_provider` in favor of a new `AddExpressionLanguageProvidersPass` in SecurityBundle.
+
4.1.0
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
index f599a5ceef9f3..b2dcc5f238e63 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
@@ -17,6 +17,7 @@
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -334,6 +335,8 @@ protected function describeContainerDefinition(Definition $definition, array $op
$argumentsInformation[] = sprintf('Service(%s)', (string) $argument);
} elseif ($argument instanceof IteratorArgument) {
$argumentsInformation[] = sprintf('Iterator (%d element(s))', \count($argument->getValues()));
+ } elseif ($argument instanceof ServiceLocatorArgument) {
+ $argumentsInformation[] = sprintf('Service locator (%d element(s))', \count($argument->getValues()));
} elseif ($argument instanceof Definition) {
$argumentsInformation[] = 'Inlined Service';
} else {
@@ -352,7 +355,11 @@ protected function describeContainerDefinition(Definition $definition, array $op
*/
protected function describeContainerAlias(Alias $alias, array $options = array(), ContainerBuilder $builder = null)
{
- $options['output']->comment(sprintf('This service is an alias for the service %s', (string) $alias));
+ if ($alias->isPublic()) {
+ $options['output']->comment(sprintf('This service is a public alias for the service %s', (string) $alias));
+ } else {
+ $options['output']->comment(sprintf('This service is a private alias for the service %s', (string) $alias));
+ }
if (!$builder) {
return;
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
index bdeb94cdd0d6b..385444d228ab0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
@@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -387,8 +388,8 @@ private function getArgumentNodes(array $arguments, \DOMDocument $dom)
if ($argument instanceof Reference) {
$argumentXML->setAttribute('type', 'service');
$argumentXML->setAttribute('id', (string) $argument);
- } elseif ($argument instanceof IteratorArgument) {
- $argumentXML->setAttribute('type', 'iterator');
+ } elseif ($argument instanceof IteratorArgument || $argument instanceof ServiceLocatorArgument) {
+ $argumentXML->setAttribute('type', $argument instanceof IteratorArgument ? 'iterator' : 'service_locator');
foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) {
$argumentXML->appendChild($childArgumentXML);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
index c782e2a718c46..552704f20d42d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
@@ -51,16 +51,22 @@ protected function createController($controller)
*/
protected function instantiateController($class)
{
- return $this->configureController(parent::instantiateController($class));
+ return $this->configureController(parent::instantiateController($class), $class);
}
- private function configureController($controller)
+ private function configureController($controller, string $class)
{
if ($controller instanceof ContainerAwareInterface) {
$controller->setContainer($this->container);
}
- if ($controller instanceof AbstractController && null !== $previousContainer = $controller->setContainer($this->container)) {
- $controller->setContainer($previousContainer);
+ if ($controller instanceof AbstractController) {
+ if (null === $previousContainer = $controller->setContainer($this->container)) {
+ @trigger_error(sprintf('Auto-injection of the container for "%s" is deprecated since Symfony 4.2. Configure it as a service instead.', $class), E_USER_DEPRECATED);
+ // To be uncommented on Symfony 5:
+ //throw new \LogicException(sprintf('"%s" has no container set, did you forget to define it as a service subscriber?', $class));
+ } else {
+ $controller->setContainer($previousContainer);
+ }
}
return $controller;
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
index a5bdfd626faec..b1bc914f1819b 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddExpressionLanguageProvidersPass.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass as SecurityExpressionLanguageProvidersPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -22,6 +23,17 @@
*/
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
+ private $handleSecurityLanguageProviders;
+
+ public function __construct(bool $handleSecurityLanguageProviders = true)
+ {
+ if ($handleSecurityLanguageProviders) {
+ @trigger_error(sprintf('Registering services tagged "security.expression_language_provider" with "%s" is deprecated since Symfony 4.2, use the "%s" instead.', __CLASS__, SecurityExpressionLanguageProvidersPass::class), E_USER_DEPRECATED);
+ }
+
+ $this->handleSecurityLanguageProviders = $handleSecurityLanguageProviders;
+ }
+
/**
* {@inheritdoc}
*/
@@ -36,7 +48,7 @@ public function process(ContainerBuilder $container)
}
// security
- if ($container->has('security.expression_language')) {
+ if ($this->handleSecurityLanguageProviders && $container->has('security.expression_language')) {
$definition = $container->findDefinition('security.expression_language');
foreach ($container->findTaggedServiceIds('security.expression_language_provider', true) as $id => $attributes) {
$definition->addMethodCall('registerProvider', array(new Reference($id)));
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
index bd6908b9c4507..d0d3665a617d8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php
@@ -30,9 +30,9 @@ public function process(ContainerBuilder $container)
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);
+ foreach ($clearer->getArgument(0) as $name => $ref) {
+ if ($container->hasDefinition($ref)) {
+ $pools[$name] = new Reference($ref);
}
}
$clearer->replaceArgument(0, $pools);
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
index b515bcb69c1e4..583c3b80ea347 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php
@@ -41,6 +41,7 @@ public function process(ContainerBuilder $container)
$clearers = array();
$attributes = array(
'provider',
+ 'name',
'namespace',
'default_lifetime',
'reset',
@@ -56,8 +57,9 @@ public function process(ContainerBuilder $container)
$tags[0] += $t[0];
}
}
+ $name = $tags[0]['name'] ?? $id;
if (!isset($tags[0]['namespace'])) {
- $tags[0]['namespace'] = $this->getNamespace($seed, $id);
+ $tags[0]['namespace'] = $this->getNamespace($seed, $name);
}
if (isset($tags[0]['clearer'])) {
$clearer = $tags[0]['clearer'];
@@ -67,7 +69,7 @@ public function process(ContainerBuilder $container)
} else {
$clearer = null;
}
- unset($tags[0]['clearer']);
+ unset($tags[0]['clearer'], $tags[0]['name']);
if (isset($tags[0]['provider'])) {
$tags[0]['provider'] = new Reference(static::getServiceProvider($container, $tags[0]['provider']));
@@ -86,14 +88,14 @@ public function process(ContainerBuilder $container)
unset($tags[0][$attr]);
}
if (!empty($tags[0])) {
- throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace", "default_lifetime" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0]))));
+ throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "name", "namespace", "default_lifetime" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0]))));
}
if (null !== $clearer) {
- $clearers[$clearer][$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
+ $clearers[$clearer][$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
}
- $pools[$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
+ $pools[$name] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE);
}
$clearer = 'cache.global_clearer';
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php
index 060d234d38772..a7d6986fa9d61 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php
@@ -11,8 +11,8 @@
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
@@ -32,7 +32,7 @@ public function process(ContainerBuilder $container)
foreach ($definitions as $id => $definition) {
if ($id && '.' !== $id[0] && (!$definition->isPublic() || $definition->isPrivate()) && !$definition->getErrors() && !$definition->isAbstract()) {
- $privateServices[$id] = new ServiceClosureArgument(new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
+ $privateServices[$id] = new Reference($id, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
}
}
@@ -44,13 +44,15 @@ public function process(ContainerBuilder $container)
$alias = $aliases[$target];
}
if (isset($definitions[$target]) && !$definitions[$target]->getErrors() && !$definitions[$target]->isAbstract()) {
- $privateServices[$id] = new ServiceClosureArgument(new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE));
+ $privateServices[$id] = new Reference($target, ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE);
}
}
}
if ($privateServices) {
- $definitions['test.private_services_locator']->replaceArgument(0, $privateServices);
+ $id = (string) ServiceLocatorTagPass::register($container, $privateServices);
+ $container->setDefinition('test.private_services_locator', $container->getDefinition($id))->setPublic(true);
+ $container->removeDefinition($id);
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
index 14c97cfaef24a..00328b4b5fbee 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
@@ -44,6 +44,7 @@ class UnusedTagsPass implements CompilerPassInterface
'messenger.receiver',
'messenger.message_handler',
'monolog.logger',
+ 'proxy',
'routing.expression_language_provider',
'routing.loader',
'security.expression_language_provider',
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 327166cf650c1..1766366252147 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -22,6 +22,7 @@
use Symfony\Component\Lock\Lock;
use Symfony\Component\Lock\Store\SemaphoreStore;
use Symfony\Component\Messenger\MessageBusInterface;
+use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Translation\Translator;
@@ -53,8 +54,8 @@ public function __construct(bool $debug)
*/
public function getConfigTreeBuilder()
{
- $treeBuilder = new TreeBuilder();
- $rootNode = $treeBuilder->root('framework');
+ $treeBuilder = new TreeBuilder('framework');
+ $rootNode = $treeBuilder->getRootNode();
$rootNode
->beforeNormalization()
@@ -370,7 +371,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->scalarNode('guard')
->cannotBeEmpty()
->info('An expression to block the transition')
- ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')
+ ->example('is_fully_authenticated() and is_granted(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'')
->end()
->arrayNode('from')
->beforeNormalization()
@@ -451,6 +452,7 @@ private function addRouterSection(ArrayNodeDefinition $rootNode)
)
->defaultTrue()
->end()
+ ->booleanNode('utf8')->defaultFalse()->end()
->end()
->end()
->end()
@@ -833,7 +835,7 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode)
->children()
->arrayNode('property_info')
->info('Property info configuration')
- ->canBeEnabled()
+ ->{!class_exists(FullStack::class) && interface_exists(PropertyInfoExtractorInterface::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->end()
->end()
;
@@ -865,11 +867,13 @@ private function addCacheSection(ArrayNodeDefinition $rootNode)
->scalarNode('default_psr6_provider')->end()
->scalarNode('default_redis_provider')->defaultValue('redis://localhost')->end()
->scalarNode('default_memcached_provider')->defaultValue('memcached://localhost')->end()
+ ->scalarNode('default_pdo_provider')->defaultValue('doctrine.dbal.default_connection')->end()
->arrayNode('pools')
->useAttributeAsKey('name')
->prototype('array')
->children()
->scalarNode('adapter')->defaultValue('cache.app')->end()
+ ->scalarNode('tags')->defaultNull()->end()
->booleanNode('public')->defaultFalse()->end()
->integerNode('default_lifetime')->end()
->scalarNode('provider')
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index b08f1bbde2068..736e98e306acb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -14,6 +14,7 @@
use Doctrine\Common\Annotations\AnnotationRegistry;
use Doctrine\Common\Annotations\Reader;
use Symfony\Bridge\Monolog\Processor\DebugProcessor;
+use Symfony\Bridge\Monolog\Processor\ProcessorInterface;
use Symfony\Bridge\Twig\Extension\CsrfExtension;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
@@ -22,6 +23,9 @@
use Symfony\Component\Cache\Adapter\AbstractAdapter;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Component\Cache\Adapter\ArrayAdapter;
+use Symfony\Component\Cache\Adapter\TagAwareAdapter;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\LoaderInterface;
@@ -92,6 +96,7 @@
use Symfony\Component\Workflow;
use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand;
use Symfony\Component\Yaml\Yaml;
+use Symfony\Contracts\Service\ResetInterface;
/**
* FrameworkExtension.
@@ -321,8 +326,16 @@ public function load(array $configs, ContainerBuilder $container)
->addTag('kernel.cache_warmer');
$container->registerForAutoconfiguration(EventSubscriberInterface::class)
->addTag('kernel.event_subscriber');
- $container->registerForAutoconfiguration(ResettableInterface::class)
+ $container->registerForAutoconfiguration(ResetInterface::class)
->addTag('kernel.reset', array('method' => 'reset'));
+
+ if (!interface_exists(MarshallerInterface::class)) {
+ $container->registerForAutoconfiguration(ResettableInterface::class)
+ ->addTag('kernel.reset', array('method' => 'reset'));
+ }
+
+ $container->registerForAutoconfiguration(ProcessorInterface::class)
+ ->addTag('monolog.processor');
$container->registerForAutoconfiguration(PropertyListExtractorInterface::class)
->addTag('property_info.list_extractor');
$container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class)
@@ -685,6 +698,9 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co
$loader->load('routing.xml');
+ if ($config['utf8']) {
+ $container->getDefinition('routing.loader')->replaceArgument(2, array('utf8' => true));
+ }
if (!interface_exists(ContainerBagInterface::class)) {
$container->getDefinition('router.default')
->replaceArgument(0, new Reference('service_container'))
@@ -1542,9 +1558,12 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
private function registerCacheConfiguration(array $config, ContainerBuilder $container)
{
+ if (!class_exists(DefaultMarshaller::class)) {
+ $container->removeDefinition('cache.default_marshaller');
+ }
+
$version = new Parameter('container.build_id');
$container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version);
- $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version);
$container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']);
if (isset($config['prefix_seed'])) {
@@ -1554,7 +1573,7 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
// Inline any env vars referenced in the parameter
$container->setParameter('cache.prefix.seed', $container->resolveEnvPlaceholders($container->getParameter('cache.prefix.seed'), true));
}
- foreach (array('doctrine', 'psr6', 'redis', 'memcached') as $name) {
+ foreach (array('doctrine', 'psr6', 'redis', 'memcached', 'pdo') as $name) {
if (isset($config[$name = 'default_'.$name.'_provider'])) {
$container->setAlias('cache.'.$name, new Alias(Compiler\CachePoolPass::getServiceProvider($container, $config[$name]), false));
}
@@ -1563,12 +1582,31 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con
$config['pools']['cache.'.$name] = array(
'adapter' => $config[$name],
'public' => true,
+ 'tags' => false,
);
}
foreach ($config['pools'] as $name => $pool) {
+ if ($config['pools'][$pool['adapter']]['tags'] ?? false) {
+ $pool['adapter'] = '.'.$pool['adapter'].'.inner';
+ }
$definition = new ChildDefinition($pool['adapter']);
+
+ if ($pool['tags']) {
+ if ($config['pools'][$pool['tags']]['tags'] ?? false) {
+ $pool['tags'] = '.'.$pool['tags'].'.inner';
+ }
+ $container->register($name, TagAwareAdapter::class)
+ ->addArgument(new Reference('.'.$name.'.inner'))
+ ->addArgument(true !== $pool['tags'] ? new Reference($pool['tags']) : null)
+ ->setPublic($pool['public'])
+ ;
+
+ $pool['name'] = $name;
+ $pool['public'] = false;
+ $name = '.'.$name.'.inner';
+ }
$definition->setPublic($pool['public']);
- unset($pool['adapter'], $pool['public']);
+ unset($pool['adapter'], $pool['public'], $pool['tags']);
$definition->addTag('cache.pool', $pool);
$container->setDefinition($name, $definition);
diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 506644d5fa320..96f09e8645acf 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -101,7 +101,7 @@ public function build(ContainerBuilder $container)
$this->addCompilerPassIfExists($container, AddConsoleCommandPass::class, PassConfig::TYPE_BEFORE_REMOVING);
$this->addCompilerPassIfExists($container, TranslatorPass::class);
$container->addCompilerPass(new LoggingTranslatorPass());
- $container->addCompilerPass(new AddExpressionLanguageProvidersPass());
+ $container->addCompilerPass(new AddExpressionLanguageProvidersPass(false));
$this->addCompilerPassIfExists($container, TranslationExtractorPass::class);
$this->addCompilerPassIfExists($container, TranslationDumperPass::class);
$container->addCompilerPass(new FragmentRendererPass());
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
index f7162adb1c701..533b3780cf15f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml
@@ -15,6 +15,10 @@
+
+
+
+
@@ -31,15 +35,16 @@
-
-
+
0
-
%kernel.cache_dir%/pools
-
+ true
+
+
+
@@ -70,6 +75,7 @@
0
%kernel.cache_dir%/pools
+
@@ -88,6 +94,7 @@
0
+
@@ -99,6 +106,20 @@
0
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
@@ -113,6 +134,10 @@
+
+ null
+
+
@@ -124,5 +149,6 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
index a893127276564..bcf2f33b10a3a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml
@@ -13,7 +13,11 @@
+
+
+
+