[DI] Remove LazyString from 4.4, before adding back to the String component
This commit is contained in:
parent
585c0df909
commit
b1a3ee76ac
@ -1473,9 +1473,13 @@ class FrameworkExtension extends Extension
|
||||
}
|
||||
|
||||
if ($config['decryption_env_var']) {
|
||||
$container->getDefinition('secrets.decryption_key')->replaceArgument(1, $config['decryption_env_var']);
|
||||
if (!preg_match('/^(?:\w*+:)*+\w++$/', $config['decryption_env_var'])) {
|
||||
throw new InvalidArgumentException(sprintf('Invalid value "%s" set as "decryption_env_var": only "word" characters are allowed.', $config['decryption_env_var']));
|
||||
}
|
||||
|
||||
$container->getDefinition('secrets.vault')->replaceArgument(1, "%env({$config['decryption_env_var']})%");
|
||||
} else {
|
||||
$container->removeDefinition('secrets.decryption_key');
|
||||
$container->getDefinition('secrets.vault')->replaceArgument(1, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,25 +7,7 @@
|
||||
<services>
|
||||
<service id="secrets.vault" class="Symfony\Bundle\FrameworkBundle\Secrets\SodiumVault">
|
||||
<argument>%kernel.project_dir%/config/secrets/%kernel.environment%</argument>
|
||||
<argument type="service" id="secrets.decryption_key" on-invalid="ignore" />
|
||||
</service>
|
||||
|
||||
<!--
|
||||
LazyString::fromCallable() is used as a wrapper to lazily read the SYMFONY_DECRYPTION_SECRET var from the env.
|
||||
By overriding this service and using the same strategy, the decryption key can be fetched lazily from any other service if needed.
|
||||
-->
|
||||
<service id="secrets.decryption_key" class="Symfony\Component\DependencyInjection\LazyString">
|
||||
<factory class="Symfony\Component\DependencyInjection\LazyString" method="fromCallable" />
|
||||
<argument type="service">
|
||||
<service class="Closure">
|
||||
<factory class="Closure" method="fromCallable" />
|
||||
<argument type="collection">
|
||||
<argument type="service" id="service_container" />
|
||||
<argument>getEnv</argument>
|
||||
</argument>
|
||||
</service>
|
||||
</argument>
|
||||
<argument>base64:default::SYMFONY_DECRYPTION_SECRET</argument>
|
||||
<argument>%env(base64:default::SYMFONY_DECRYPTION_SECRET)%</argument>
|
||||
</service>
|
||||
|
||||
<service id="secrets.local_vault" class="Symfony\Bundle\FrameworkBundle\Secrets\DotenvVault">
|
||||
|
@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
$container->setParameter('env(REDIS_URL)', 'redis://paas.com');
|
||||
|
||||
$container->loadFromExtension('framework', [
|
||||
'cache' => [
|
||||
'default_redis_provider' => '%env(REDIS_URL)%',
|
||||
],
|
||||
]);
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<container xmlns="http://symfony.com/schema/dic/services"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:framework="http://symfony.com/schema/dic/symfony"
|
||||
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<parameters>
|
||||
<parameter key="env(REDIS_URL)">redis://paas.com</parameter>
|
||||
</parameters>
|
||||
|
||||
<framework:config>
|
||||
<framework:cache>
|
||||
<framework:default-redis-provider>%env(REDIS_URL)%</framework:default-redis-provider>
|
||||
</framework:cache>
|
||||
</framework:config>
|
||||
</container>
|
@ -1,6 +0,0 @@
|
||||
parameters:
|
||||
env(REDIS_URL): redis://paas.com
|
||||
|
||||
framework:
|
||||
cache:
|
||||
default_redis_provider: "%env(REDIS_URL)%"
|
@ -34,7 +34,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpClient\ScopingHttpClient;
|
||||
@ -1403,20 +1403,6 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertSame($redisUrl, $url);
|
||||
}
|
||||
|
||||
public function testCacheDefaultRedisProviderWithEnvVar()
|
||||
{
|
||||
$container = $this->createContainerFromFile('cache_env_var');
|
||||
|
||||
$redisUrl = 'redis://paas.com';
|
||||
$providerId = '.cache_connection.'.ContainerBuilder::hash($redisUrl);
|
||||
|
||||
$this->assertTrue($container->hasDefinition($providerId));
|
||||
|
||||
$url = $container->getDefinition($providerId)->getArgument(0);
|
||||
|
||||
$this->assertSame($redisUrl, $url);
|
||||
}
|
||||
|
||||
public function testCachePoolServices()
|
||||
{
|
||||
$container = $this->createContainerFromFile('cache', [], true, false);
|
||||
@ -1584,7 +1570,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
|
||||
protected function createContainer(array $data = [])
|
||||
{
|
||||
return new ContainerBuilder(new ParameterBag(array_merge([
|
||||
return new ContainerBuilder(new EnvPlaceholderParameterBag(array_merge([
|
||||
'kernel.bundles' => ['FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'],
|
||||
'kernel.bundles_metadata' => ['FrameworkBundle' => ['namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..']],
|
||||
'kernel.cache_dir' => __DIR__,
|
||||
|
@ -14,7 +14,6 @@ CHANGELOG
|
||||
* made singly-implemented interfaces detection be scoped by file
|
||||
* added ability to define a static priority method for tagged service
|
||||
* added support for improved syntax to define method calls in Yaml
|
||||
* added `LazyString` for lazy computation of string values injected into services
|
||||
* made the `%env(base64:...)%` processor able to decode base64url
|
||||
* added ability to choose behavior of decorations on non existent decorated services
|
||||
|
||||
|
@ -1,112 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection;
|
||||
|
||||
/**
|
||||
* A string whose value is computed lazily by a callback.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class LazyString
|
||||
{
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @param callable $callback A callable or a [Closure, method] lazy-callable
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function fromCallable($callback, ...$arguments): self
|
||||
{
|
||||
if (!\is_callable($callback) && !(\is_array($callback) && isset($callback[0]) && $callback[0] instanceof \Closure && 2 >= \count($callback))) {
|
||||
throw new \TypeError(sprintf('Argument 1 passed to %s() must be a callable or a [Closure, method] lazy-callable, %s given.', __METHOD__, \gettype($callback)));
|
||||
}
|
||||
|
||||
$lazyString = new static();
|
||||
$lazyString->value = static function () use (&$callback, &$arguments, &$value): string {
|
||||
if (null !== $arguments) {
|
||||
if (!\is_callable($callback)) {
|
||||
$callback[0] = $callback[0]();
|
||||
$callback[1] = $callback[1] ?? '__invoke';
|
||||
}
|
||||
$value = $callback(...$arguments);
|
||||
$callback = self::getPrettyName($callback);
|
||||
$arguments = null;
|
||||
}
|
||||
|
||||
return $value ?? '';
|
||||
};
|
||||
|
||||
return $lazyString;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
if (\is_string($this->value)) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->value = ($this->value)();
|
||||
} catch (\Throwable $e) {
|
||||
if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) {
|
||||
$type = explode(', ', $e->getMessage());
|
||||
$type = substr(array_pop($type), 0, -\strlen(' returned'));
|
||||
$r = new \ReflectionFunction($this->value);
|
||||
$callback = $r->getStaticVariables()['callback'];
|
||||
|
||||
$e = new \TypeError(sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID < 70400) {
|
||||
// leverage the ErrorHandler component with graceful fallback when it's not available
|
||||
return trigger_error($e, E_USER_ERROR);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
private static function getPrettyName(callable $callback): string
|
||||
{
|
||||
if (\is_string($callback)) {
|
||||
return $callback;
|
||||
}
|
||||
|
||||
if (\is_array($callback)) {
|
||||
$class = \is_object($callback[0]) ? \get_class($callback[0]) : $callback[0];
|
||||
$method = $callback[1];
|
||||
} elseif ($callback instanceof \Closure) {
|
||||
$r = new \ReflectionFunction($callback);
|
||||
|
||||
if (false !== strpos($r->name, '{closure}') || !$class = $r->getClosureScopeClass()) {
|
||||
return $r->name;
|
||||
}
|
||||
|
||||
$class = $class->name;
|
||||
$method = $r->name;
|
||||
} else {
|
||||
$class = \get_class($callback);
|
||||
$method = '__invoke';
|
||||
}
|
||||
|
||||
if (isset($class[15]) && "\0" === $class[15] && 0 === strpos($class, "class@anonymous\x00")) {
|
||||
$class = get_parent_class($class).'@anonymous';
|
||||
}
|
||||
|
||||
return $class.'::'.$method;
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\LazyString;
|
||||
use Symfony\Component\ErrorHandler\ErrorHandler;
|
||||
|
||||
class LazyStringTest extends TestCase
|
||||
{
|
||||
public function testLazyString()
|
||||
{
|
||||
$count = 0;
|
||||
$s = LazyString::fromCallable(function () use (&$count) {
|
||||
return ++$count;
|
||||
});
|
||||
|
||||
$this->assertSame(0, $count);
|
||||
$this->assertSame('1', (string) $s);
|
||||
$this->assertSame(1, $count);
|
||||
}
|
||||
|
||||
public function testLazyCallable()
|
||||
{
|
||||
$count = 0;
|
||||
$s = LazyString::fromCallable([function () use (&$count) {
|
||||
return new class($count) {
|
||||
private $count;
|
||||
|
||||
public function __construct(int &$count)
|
||||
{
|
||||
$this->count = &$count;
|
||||
}
|
||||
|
||||
public function __invoke()
|
||||
{
|
||||
return ++$this->count;
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
$this->assertSame(0, $count);
|
||||
$this->assertSame('1', (string) $s);
|
||||
$this->assertSame(1, $count);
|
||||
$this->assertSame('1', (string) $s); // ensure the value is memoized
|
||||
$this->assertSame(1, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testReturnTypeError()
|
||||
{
|
||||
ErrorHandler::register();
|
||||
|
||||
$s = LazyString::fromCallable(function () { return []; });
|
||||
|
||||
$this->expectException(\TypeError::class);
|
||||
$this->expectExceptionMessage('Return value of '.__NAMESPACE__.'\{closure}() passed to '.LazyString::class.'::fromCallable() must be of the type string, array returned.');
|
||||
|
||||
(string) $s;
|
||||
}
|
||||
}
|
@ -23,7 +23,6 @@
|
||||
"require-dev": {
|
||||
"symfony/yaml": "^3.4|^4.0|^5.0",
|
||||
"symfony/config": "^4.3|^5.0",
|
||||
"symfony/error-handler": "^4.4|^5.0",
|
||||
"symfony/expression-language": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"suggest": {
|
||||
|
Reference in New Issue
Block a user