Merge branch '4.4' into 5.0
* 4.4: [Mailer] fix typos [Messenger] fix typo [DI] Unknown env prefix not regornized as such [DI] Fix support for multiple tags for locators and iterators [PhpUnitBridge] Fix some errors when using serialized deprecations Fix HTTP client config handling
This commit is contained in:
commit
74a42d102f
@ -99,7 +99,19 @@ class DeprecationErrorHandler
|
||||
return \call_user_func(self::getPhpUnitErrorHandler(), $type, $msg, $file, $line, $context);
|
||||
}
|
||||
|
||||
$deprecations[] = [error_reporting(), $msg, $file];
|
||||
$trace = debug_backtrace();
|
||||
$filesStack = [];
|
||||
foreach ($trace as $line) {
|
||||
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($line['file'])) {
|
||||
$filesStack[] = $line['file'];
|
||||
}
|
||||
}
|
||||
|
||||
$deprecations[] = [error_reporting(), $msg, $file, $filesStack];
|
||||
|
||||
return null;
|
||||
});
|
||||
|
@ -44,6 +44,8 @@ class Deprecation
|
||||
*/
|
||||
private static $internalPaths = [];
|
||||
|
||||
private $originalFilesStack;
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param string $file
|
||||
@ -64,6 +66,7 @@ class Deprecation
|
||||
$this->message = $parsedMsg['deprecation'];
|
||||
$this->originClass = $parsedMsg['class'];
|
||||
$this->originMethod = $parsedMsg['method'];
|
||||
$this->originalFilesStack = $parsedMsg['files_stack'];
|
||||
// If the deprecation has been triggered via
|
||||
// \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest()
|
||||
// then we need to use the serialized information to determine
|
||||
@ -162,6 +165,24 @@ class Deprecation
|
||||
return false !== strpos($this->triggeringFile, \DIRECTORY_SEPARATOR.'vendor'.\DIRECTORY_SEPARATOR.'phpunit'.\DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
private function getOriginalFilesStack(): array
|
||||
{
|
||||
if (null === $this->originalFilesStack) {
|
||||
$this->originalFilesStack = [];
|
||||
foreach ($this->trace as $line) {
|
||||
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($line['file'])) {
|
||||
continue;
|
||||
}
|
||||
$this->originalFilesStack[] = $line['file'];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->originalFilesStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether both the calling package and the called package are vendor
|
||||
* packages.
|
||||
@ -178,14 +199,8 @@ class Deprecation
|
||||
return self::TYPE_UNDETERMINED;
|
||||
}
|
||||
$erroringFile = $erroringPackage = null;
|
||||
foreach ($this->trace as $line) {
|
||||
if (\in_array($line['function'], ['require', 'require_once', 'include', 'include_once'], true)) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($line['file'])) {
|
||||
continue;
|
||||
}
|
||||
$file = $line['file'];
|
||||
|
||||
foreach ($this->getOriginalFilesStack() as $file) {
|
||||
if ('-' === $file || 'Standard input code' === $file || !realpath($file)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -11,12 +11,32 @@
|
||||
|
||||
namespace Symfony\Bridge\PhpUnit\Tests\DeprecationErrorHandler;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler;
|
||||
use Symfony\Bridge\PhpUnit\DeprecationErrorHandler\Deprecation;
|
||||
use Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerForV5;
|
||||
|
||||
class DeprecationTest extends TestCase
|
||||
{
|
||||
public static function setUpBeforeClass(): void
|
||||
{
|
||||
$vendorDir = self::getVendorDir();
|
||||
|
||||
mkdir($vendorDir.'/myfakevendor/myfakepackage1', 0777, true);
|
||||
mkdir($vendorDir.'/myfakevendor/myfakepackage2');
|
||||
touch($vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php');
|
||||
touch($vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile2.php');
|
||||
touch($vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php');
|
||||
}
|
||||
|
||||
private static function getVendorDir(): string
|
||||
{
|
||||
$reflection = new \ReflectionClass(ClassLoader::class);
|
||||
|
||||
return \dirname($reflection->getFileName(), 2);
|
||||
}
|
||||
|
||||
public function testItCanDetermineTheClassWhereTheDeprecationHappened()
|
||||
{
|
||||
$deprecation = new Deprecation('💩', $this->debugBacktrace(), __FILE__);
|
||||
@ -118,12 +138,135 @@ class DeprecationTest extends TestCase
|
||||
$this->assertTrue($deprecation->isMuted());
|
||||
}
|
||||
|
||||
public function providerGetTypeDetectsSelf(): array
|
||||
{
|
||||
foreach (get_declared_classes() as $class) {
|
||||
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
|
||||
$r = new \ReflectionClass($class);
|
||||
$v = \dirname(\dirname($r->getFileName()));
|
||||
if (file_exists($v.'/composer/installed.json')) {
|
||||
$loader = require $v.'/autoload.php';
|
||||
$reflection = new \ReflectionClass($loader);
|
||||
$prop = $reflection->getProperty('prefixDirsPsr4');
|
||||
$prop->setAccessible(true);
|
||||
$currentValue = $prop->getValue($loader);
|
||||
$currentValue['Symfony\\Bridge\\PhpUnit\\'] = [realpath(__DIR__.'/../..')];
|
||||
$prop->setValue($loader, $currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'not_from_vendors_file' => [Deprecation::TYPE_SELF, '', 'MyClass1', ''],
|
||||
'nonexistent_file' => [Deprecation::TYPE_UNDETERMINED, '', 'MyClass1', 'dummy_vendor_path'],
|
||||
'serialized_trace_with_nonexistent_triggering_file' => [
|
||||
Deprecation::TYPE_UNDETERMINED,
|
||||
serialize([
|
||||
'class' => '',
|
||||
'method' => '',
|
||||
'deprecation' => '',
|
||||
'triggering_file' => 'dummy_vendor_path',
|
||||
'files_stack' => [],
|
||||
]),
|
||||
SymfonyTestsListenerForV5::class,
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerGetTypeDetectsSelf
|
||||
*/
|
||||
public function testGetTypeDetectsSelf(string $expectedType, string $message, string $traceClass, string $file): void
|
||||
{
|
||||
$trace = [
|
||||
['class' => 'MyClass1', 'function' => 'myMethod'],
|
||||
['class' => $traceClass, 'function' => 'myMethod'],
|
||||
];
|
||||
$deprecation = new Deprecation($message, $trace, $file);
|
||||
$this->assertEquals($expectedType, $deprecation->getType());
|
||||
}
|
||||
|
||||
public function providerGetTypeUsesRightTrace(): array
|
||||
{
|
||||
$vendorDir = self::getVendorDir();
|
||||
|
||||
return [
|
||||
'no_file_in_stack' => [Deprecation::TYPE_DIRECT, '', [['function' => 'myfunc1'], ['function' => 'myfunc2']]],
|
||||
'files_in_stack_from_various_packages' => [
|
||||
Deprecation::TYPE_INDIRECT,
|
||||
'',
|
||||
[
|
||||
['function' => 'myfunc1', 'file' => $vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php'],
|
||||
['function' => 'myfunc2', 'file' => $vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php'],
|
||||
],
|
||||
],
|
||||
'serialized_stack_files_from_same_package' => [
|
||||
Deprecation::TYPE_DIRECT,
|
||||
serialize([
|
||||
'deprecation' => 'My deprecation message',
|
||||
'class' => 'MyClass',
|
||||
'method' => 'myMethod',
|
||||
'files_stack' => [
|
||||
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php',
|
||||
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile2.php',
|
||||
],
|
||||
]),
|
||||
[['function' => 'myfunc1'], ['class' => SymfonyTestsListenerForV5::class, 'method' => 'mymethod']],
|
||||
],
|
||||
'serialized_stack_files_from_various_packages' => [
|
||||
Deprecation::TYPE_INDIRECT,
|
||||
serialize([
|
||||
'deprecation' => 'My deprecation message',
|
||||
'class' => 'MyClass',
|
||||
'method' => 'myMethod',
|
||||
'files_stack' => [
|
||||
$vendorDir.'/myfakevendor/myfakepackage1/MyFakeFile1.php',
|
||||
$vendorDir.'/myfakevendor/myfakepackage2/MyFakeFile.php',
|
||||
],
|
||||
]),
|
||||
[['function' => 'myfunc1'], ['class' => SymfonyTestsListenerForV5::class, 'method' => 'mymethod']],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerGetTypeUsesRightTrace
|
||||
*/
|
||||
public function testGetTypeUsesRightTrace(string $expectedType, string $message, array $trace): void
|
||||
{
|
||||
$deprecation = new Deprecation(
|
||||
$message,
|
||||
$trace,
|
||||
self::getVendorDir().'/myfakevendor/myfakepackage2/MyFakeFile.php'
|
||||
);
|
||||
$this->assertEquals($expectedType, $deprecation->getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is here to simulate the extra level from the piece of code
|
||||
* triggering an error to the error handler
|
||||
* triggering an error to the error handler.
|
||||
*/
|
||||
public function debugBacktrace(): array
|
||||
{
|
||||
return debug_backtrace();
|
||||
}
|
||||
|
||||
private static function removeDir($dir): void
|
||||
{
|
||||
$files = glob($dir.'/*');
|
||||
foreach ($files as $file) {
|
||||
if (is_file($file)) {
|
||||
unlink($file);
|
||||
} else {
|
||||
self::removeDir($file);
|
||||
}
|
||||
}
|
||||
rmdir($dir);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass(): void
|
||||
{
|
||||
self::removeDir(self::getVendorDir().'/myfakevendor');
|
||||
}
|
||||
}
|
||||
|
@ -1265,7 +1265,7 @@ class Configuration implements ConfigurationInterface
|
||||
if (!\is_array($config)) {
|
||||
return [];
|
||||
}
|
||||
if (!isset($config['host'])) {
|
||||
if (!isset($config['host'], $config['value']) || \count($config) > 2) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
@ -1374,7 +1374,7 @@ class Configuration implements ConfigurationInterface
|
||||
if (!\is_array($config)) {
|
||||
return [];
|
||||
}
|
||||
if (!isset($config['key'])) {
|
||||
if (!isset($config['key'], $config['value']) || \count($config) > 2) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
@ -1404,7 +1404,7 @@ class Configuration implements ConfigurationInterface
|
||||
if (!\is_array($config)) {
|
||||
return [];
|
||||
}
|
||||
if (!isset($config['host'])) {
|
||||
if (!isset($config['host'], $config['value']) || \count($config) > 2) {
|
||||
return $config;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
$container->loadFromExtension('framework', [
|
||||
'http_client' => [
|
||||
'default_options' => [
|
||||
'resolve' => [
|
||||
'host' => '127.0.0.1',
|
||||
],
|
||||
],
|
||||
'scoped_clients' => [
|
||||
'foo' => [
|
||||
'base_uri' => 'http://example.com',
|
||||
'query' => [
|
||||
'key' => 'foo',
|
||||
],
|
||||
'resolve' => [
|
||||
'host' => '127.0.0.1',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<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 http://symfony.com/schema/dic/services/services-1.0.xsd
|
||||
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
|
||||
|
||||
<framework:config>
|
||||
<framework:http-client>
|
||||
<framework:default-options>
|
||||
<framework:resolve host="host">127.0.0.1</framework:resolve>
|
||||
</framework:default-options>
|
||||
<framework:scoped-client name="foo" base-uri="http://example.com">
|
||||
<framework:query key="key">foo</framework:query>
|
||||
<framework:resolve host="host">127.0.0.1</framework:resolve>
|
||||
</framework:scoped-client>
|
||||
</framework:http-client>
|
||||
</framework:config>
|
||||
</container>
|
@ -0,0 +1,12 @@
|
||||
framework:
|
||||
http_client:
|
||||
default_options:
|
||||
resolve:
|
||||
host: 127.0.0.1
|
||||
scoped_clients:
|
||||
foo:
|
||||
base_uri: http://example.com
|
||||
query:
|
||||
key: foo
|
||||
resolve:
|
||||
host: 127.0.0.1
|
@ -1358,6 +1358,21 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(2));
|
||||
}
|
||||
|
||||
public function testHttpClientWithQueryParameterKey()
|
||||
{
|
||||
$container = $this->createContainerFromFile('http_client_xml_key');
|
||||
|
||||
$expected = [
|
||||
'key' => 'foo',
|
||||
];
|
||||
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(2)['query']);
|
||||
|
||||
$expected = [
|
||||
'host' => '127.0.0.1',
|
||||
];
|
||||
$this->assertSame($expected, $container->getDefinition('foo')->getArgument(2)['resolve']);
|
||||
}
|
||||
|
||||
public function testHttpClientFullDefaultOptions()
|
||||
{
|
||||
$container = $this->createContainerFromFile('http_client_full_default_options');
|
||||
|
@ -54,78 +54,81 @@ trait PriorityTaggedServiceTrait
|
||||
|
||||
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
|
||||
$class = $r = null;
|
||||
$priority = 0;
|
||||
if (isset($attributes[0]['priority'])) {
|
||||
$priority = $attributes[0]['priority'];
|
||||
} elseif ($defaultPriorityMethod) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
|
||||
if (($r = $container->getReflectionClass($class)) && $r->hasMethod($defaultPriorityMethod)) {
|
||||
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
$defaultPriority = null;
|
||||
$defaultIndex = null;
|
||||
|
||||
if (!$rm->isPublic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
foreach ($attributes as $attribute) {
|
||||
$index = $priority = null;
|
||||
|
||||
$priority = $rm->invoke(null);
|
||||
if (isset($attribute['priority'])) {
|
||||
$priority = $attribute['priority'];
|
||||
} elseif (null === $defaultPriority && $defaultPriorityMethod) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
|
||||
if (!\is_int($priority)) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId));
|
||||
if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultPriorityMethod)) {
|
||||
if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
|
||||
if (!$rm->isPublic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s".', $class, $defaultPriorityMethod, $tagName, $serviceId));
|
||||
}
|
||||
|
||||
$defaultPriority = $rm->invoke(null);
|
||||
|
||||
if (!\is_int($defaultPriority)) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer, got %s: tag "%s" on service "%s".', $class, $defaultPriorityMethod, \gettype($priority), $tagName, $serviceId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $indexAttribute && !$needsIndexes) {
|
||||
$services[$priority][] = new Reference($serviceId);
|
||||
$priority = $priority ?? $defaultPriority ?? 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
|
||||
$index = $attribute[$indexAttribute];
|
||||
} elseif (null === $defaultIndex && null === $indexAttribute && !$needsIndexes) {
|
||||
// With partially associative array, insertion to get next key is simpler.
|
||||
$services[$priority][] = null;
|
||||
end($services[$priority]);
|
||||
$defaultIndex = key($services[$priority]);
|
||||
} elseif (null === $defaultIndex && $defaultIndexMethod) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
|
||||
if (!$class) {
|
||||
$class = $container->getDefinition($serviceId)->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($class) ?: null;
|
||||
}
|
||||
if (($r = ($r ?? $container->getReflectionClass($class))) && $r->hasMethod($defaultIndexMethod)) {
|
||||
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
|
||||
if (null !== $indexAttribute && isset($attributes[0][$indexAttribute])) {
|
||||
$services[$priority][$attributes[0][$indexAttribute]] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $attributes[0][$indexAttribute]);
|
||||
if (!$rm->isPublic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
$defaultIndex = $rm->invoke(null);
|
||||
|
||||
if (!$r && !$r = $container->getReflectionClass($class)) {
|
||||
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $serviceId));
|
||||
}
|
||||
if (!\is_string($defaultIndex)) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($defaultIndex), $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
}
|
||||
|
||||
$class = $r->name;
|
||||
|
||||
if (!$r->hasMethod($defaultIndexMethod)) {
|
||||
if ($needsIndexes) {
|
||||
$services[$priority][$serviceId] = new TypedReference($serviceId, $class);
|
||||
|
||||
continue;
|
||||
$defaultIndex = $defaultIndex ?? $serviceId;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" not found: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
|
||||
$index = $index ?? $defaultIndex;
|
||||
|
||||
$reference = null;
|
||||
if (!$class || 'stdClass' === $class) {
|
||||
$reference = new Reference($serviceId);
|
||||
} elseif ($index === $serviceId) {
|
||||
$reference = new TypedReference($serviceId, $class);
|
||||
} else {
|
||||
$reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, \is_string($index) ? $index : null);
|
||||
}
|
||||
|
||||
$services[$priority][$index] = $reference;
|
||||
}
|
||||
|
||||
if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be static: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
|
||||
if (!$rm->isPublic()) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should be public: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
|
||||
$key = $rm->invoke(null);
|
||||
|
||||
if (!\is_string($key)) {
|
||||
throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return a string, got %s: tag "%s" on service "%s" is missing "%s" attribute.', $class, $defaultIndexMethod, \gettype($key), $tagName, $serviceId, $indexAttribute));
|
||||
}
|
||||
|
||||
$services[$priority][$key] = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $key);
|
||||
}
|
||||
|
||||
if ($services) {
|
||||
|
@ -126,9 +126,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
}
|
||||
|
||||
if (false !== $i || 'string' !== $prefix) {
|
||||
if (null === $env = $getEnv($name)) {
|
||||
return null;
|
||||
}
|
||||
$env = $getEnv($name);
|
||||
} elseif (isset($_ENV[$name])) {
|
||||
$env = $_ENV[$name];
|
||||
} elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) {
|
||||
@ -173,12 +171,18 @@ class EnvVarProcessor implements EnvVarProcessorInterface
|
||||
throw new EnvNotFoundException(sprintf('Environment variable not found: "%s".', $name));
|
||||
}
|
||||
|
||||
if (null === $env = $this->container->getParameter("env($name)")) {
|
||||
return null;
|
||||
}
|
||||
$env = $this->container->getParameter("env($name)");
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $env) {
|
||||
if (!isset($this->getProvidedTypes()[$prefix])) {
|
||||
throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_scalar($env)) {
|
||||
throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to %s.', $name, $prefix));
|
||||
}
|
||||
|
@ -314,6 +314,32 @@ class IntegrationTest extends TestCase
|
||||
$this->assertSame(['bar_tab_class_with_defaultmethod' => $container->get(BarTagClass::class), 'foo' => $container->get(FooTagClass::class)], $param);
|
||||
}
|
||||
|
||||
public function testTaggedIteratorWithMultipleIndexAttribute()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(BarTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar', ['foo' => 'bar'])
|
||||
->addTag('foo_bar', ['foo' => 'bar_duplicate'])
|
||||
;
|
||||
$container->register(FooTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar')
|
||||
->addTag('foo_bar')
|
||||
;
|
||||
$container->register(FooBarTaggedClass::class)
|
||||
->addArgument(new TaggedIteratorArgument('foo_bar', 'foo'))
|
||||
->setPublic(true)
|
||||
;
|
||||
|
||||
$container->compile();
|
||||
|
||||
$s = $container->get(FooBarTaggedClass::class);
|
||||
|
||||
$param = iterator_to_array($s->getParam()->getIterator());
|
||||
$this->assertSame(['bar' => $container->get(BarTagClass::class), 'bar_duplicate' => $container->get(BarTagClass::class), 'foo_tag_class' => $container->get(FooTagClass::class)], $param);
|
||||
}
|
||||
|
||||
public function testTaggedServiceWithDefaultPriorityMethod()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
@ -350,7 +376,7 @@ class IntegrationTest extends TestCase
|
||||
->addTag('foo_bar')
|
||||
;
|
||||
$container->register('foo_bar_tagged', FooBarTaggedClass::class)
|
||||
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo_bar', 'foo')))
|
||||
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo_bar', 'foo', null, true)))
|
||||
->setPublic(true)
|
||||
;
|
||||
|
||||
@ -369,6 +395,40 @@ class IntegrationTest extends TestCase
|
||||
$this->assertSame(['bar' => $container->get('bar_tag'), 'foo_tag_class' => $container->get('foo_tag')], $same);
|
||||
}
|
||||
|
||||
public function testTaggedServiceLocatorWithMultipleIndexAttribute()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register('bar_tag', BarTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar', ['foo' => 'bar'])
|
||||
->addTag('foo_bar', ['foo' => 'bar_duplicate'])
|
||||
;
|
||||
$container->register('foo_tag', FooTagClass::class)
|
||||
->setPublic(true)
|
||||
->addTag('foo_bar')
|
||||
->addTag('foo_bar')
|
||||
;
|
||||
$container->register('foo_bar_tagged', FooBarTaggedClass::class)
|
||||
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo_bar', 'foo', null, true)))
|
||||
->setPublic(true)
|
||||
;
|
||||
|
||||
$container->compile();
|
||||
|
||||
$s = $container->get('foo_bar_tagged');
|
||||
|
||||
/** @var ServiceLocator $serviceLocator */
|
||||
$serviceLocator = $s->getParam();
|
||||
$this->assertTrue($s->getParam() instanceof ServiceLocator, sprintf('Wrong instance, should be an instance of ServiceLocator, %s given', \is_object($serviceLocator) ? \get_class($serviceLocator) : \gettype($serviceLocator)));
|
||||
|
||||
$same = [
|
||||
'bar' => $serviceLocator->get('bar'),
|
||||
'bar_duplicate' => $serviceLocator->get('bar_duplicate'),
|
||||
'foo_tag_class' => $serviceLocator->get('foo_tag_class'),
|
||||
];
|
||||
$this->assertSame(['bar' => $container->get('bar_tag'), 'bar_duplicate' => $container->get('bar_tag'), 'foo_tag_class' => $container->get('foo_tag')], $same);
|
||||
}
|
||||
|
||||
public function testTaggedServiceLocatorWithIndexAttributeAndDefaultMethod()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
@ -381,7 +441,7 @@ class IntegrationTest extends TestCase
|
||||
->addTag('foo_bar', ['foo' => 'foo'])
|
||||
;
|
||||
$container->register('foo_bar_tagged', FooBarTaggedClass::class)
|
||||
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo_bar', 'foo', 'getFooBar')))
|
||||
->addArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('foo_bar', 'foo', 'getFooBar', true)))
|
||||
->setPublic(true)
|
||||
;
|
||||
|
||||
|
@ -9,6 +9,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\EnvVarLoaderInterface;
|
||||
use Symfony\Component\DependencyInjection\EnvVarProcessor;
|
||||
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
class EnvVarProcessorTest extends TestCase
|
||||
{
|
||||
@ -595,4 +596,17 @@ CSV;
|
||||
|
||||
$this->assertSame(2, $index);
|
||||
}
|
||||
|
||||
public function testGetEnvInvalidPrefixWithDefault()
|
||||
{
|
||||
$this->expectException(RuntimeException::class);
|
||||
$this->expectExceptionMessage('Unsupported env var prefix');
|
||||
$processor = new EnvVarProcessor(new Container());
|
||||
|
||||
$processor->getEnv('unknown', 'default::FAKE', function ($name) {
|
||||
$this->assertSame('default::FAKE', $name);
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Mailer\Exception\TransportException;
|
||||
use Symfony\Component\Mailer\SentMessage;
|
||||
use Symfony\Component\Mailer\SmtpEnvelope;
|
||||
use Symfony\Component\Mailer\Transport\Http\AbstractHttpTransport;
|
||||
use Symfony\Component\Mailer\Transport\AbstractHttpTransport;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
|
@ -57,7 +57,7 @@ class MandrillHttpTransportTest extends TestCase
|
||||
$body = json_decode($options['body'], true);
|
||||
$message = $body['raw_message'];
|
||||
$this->assertSame('KEY', $body['key']);
|
||||
$this->assertSame('Saif Eddin <saif.gmati@symfony.com>', $body['to'][0]);
|
||||
$this->assertSame('saif.gmati@symfony.com', $body['to'][0]);
|
||||
$this->assertSame('Fabien <fabpot@symfony.com>', $body['from_email']);
|
||||
|
||||
$this->assertStringContainsString('Subject: Hello!', $message);
|
||||
|
@ -47,7 +47,9 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
$response = $this->client->request('POST', 'https://'.$this->getEndpoint().'/api/1.0/messages/send-raw.json', [
|
||||
'json' => [
|
||||
'key' => $this->key,
|
||||
'to' => $this->getRecipients($envelope->getRecipients()),
|
||||
'to' => array_map(function (Address $recipient): string {
|
||||
return $recipient->getAddress();
|
||||
}, $envelope->getRecipients()),
|
||||
'from_email' => $envelope->getSender()->toString(),
|
||||
'raw_message' => $message->toString(),
|
||||
],
|
||||
@ -71,14 +73,4 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
{
|
||||
return ($this->host ?: self::HOST).($this->port ? ':'.$this->port : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getRecipients(Envelope $envelope): array
|
||||
{
|
||||
return array_map(function (Address $recipient): string {
|
||||
return $recipient->getAddress();
|
||||
}, $envelope->getRecipients());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user