diff --git a/src/Symfony/Component/Console/Output/ConsoleOutput.php b/src/Symfony/Component/Console/Output/ConsoleOutput.php index 96664f1508..2cda213a04 100644 --- a/src/Symfony/Component/Console/Output/ConsoleOutput.php +++ b/src/Symfony/Component/Console/Output/ConsoleOutput.php @@ -41,6 +41,13 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + if (null === $formatter) { + // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter. + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated); + + return; + } + $actualDecorated = $this->isDecorated(); $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); diff --git a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php index db39a02b8a..33a5371d6e 100644 --- a/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php +++ b/src/Symfony/Component/Console/Tests/Output/ConsoleOutputTest.php @@ -18,11 +18,19 @@ use Symfony\Component\Console\Output\Output; class ConsoleOutputTest extends TestCase { - public function testConstructor() + public function testConstructorWithoutFormatter() { $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true); $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); - $this->assertSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), '__construct() takes a formatter or null as the third argument'); + $this->assertNotSame($output->getFormatter(), $output->getErrorOutput()->getFormatter(), 'ErrorOutput should use it own formatter'); + } + + public function testConstructorWithFormatter() + { + $output = new ConsoleOutput(Output::VERBOSITY_QUIET, true, $formatter = new OutputFormatter()); + $this->assertEquals(Output::VERBOSITY_QUIET, $output->getVerbosity(), '__construct() takes the verbosity as its first argument'); + $this->assertSame($formatter, $output->getFormatter()); + $this->assertSame($formatter, $output->getErrorOutput()->getFormatter(), 'Output and ErrorOutput should use the same provided formatter'); } public function testSetFormatter() @@ -31,6 +39,7 @@ class ConsoleOutputTest extends TestCase $outputFormatter = new OutputFormatter(); $output->setFormatter($outputFormatter); $this->assertSame($outputFormatter, $output->getFormatter()); + $this->assertSame($outputFormatter, $output->getErrorOutput()->getFormatter()); } public function testSetVerbosity() diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d7f714c9be..5267f6fbb9 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1167,7 +1167,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface return $this->resolveServices($reference); }; } elseif ($value instanceof IteratorArgument) { - $value = new RewindableGenerator(function () use ($value) { + $value = new RewindableGenerator(function () use ($value, &$inlineServices) { foreach ($value->getValues() as $k => $v) { foreach (self::getServiceConditionals($v) as $s) { if (!$this->has($s)) { @@ -1175,12 +1175,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface } } foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { continue 2; } } - yield $k => $this->resolveServices($v); + yield $k => $this->doResolveServices($v, $inlineServices); } }, function () use ($value): int { $count = 0; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 0e8adf9a95..425c18b8d1 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -471,7 +471,7 @@ EOF; foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); - if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { + if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isWeak()) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 375187a936..df6f06653e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1393,6 +1393,10 @@ class ContainerBuilderTest extends TestCase public function testAlmostCircular($visibility) { $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php'; + $container->compile(); + + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index b87a6b8a24..3b77b7ed6e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -1054,6 +1054,9 @@ class PhpDumperTest extends TestCase $container = new $container(); + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); + $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php index a1f885399b..96c714493e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php @@ -1,5 +1,6 @@ register('monolog.logger', 'stdClass')->setPublic(true) + ->setProperty('handler', new Reference('mailer.transport')); + +$container->register('mailer.transport', 'stdClass')->setPublic($public) + ->setFactory([new Reference('mailer.transport_factory'), 'create']); + +$container->register('mailer.transport_factory', FactoryCircular::class)->setPublic($public) + ->addArgument(new TaggedIteratorArgument('mailer.transport')); + +$container->register('mailer.transport_factory.amazon', 'stdClass')->setPublic($public) + ->addArgument(new Reference('monolog.logger_2')) + ->addTag('mailer.transport'); + +$container->register('monolog.logger_2', 'stdClass')->setPublic($public) + ->setProperty('handler', new Reference('mailer.transport')); + // same visibility for deps $container->register('foo', FooCircular::class)->setPublic(true) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index fee80ac779..b22e8bcffc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -111,6 +111,23 @@ class LazyContext } } +class FactoryCircular +{ + public $services; + + public function __construct($services) + { + $this->services = $services; + } + + public function create() + { + foreach ($this->services as $service) { + return $service; + } + } +} + class FoobarCircular { public function __construct(FooCircular $foo) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php index 60c60b3adf..8bc0146fb1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php @@ -36,6 +36,7 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -77,7 +78,11 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container 'level5' => true, 'level6' => true, 'logger2' => true, + 'mailer.transport' => true, + 'mailer.transport_factory' => true, + 'mailer.transport_factory.amazon' => true, 'manager4' => true, + 'monolog.logger_2' => true, 'multiuse1' => true, 'subscriber2' => true, ]; @@ -352,6 +357,20 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container return $this->services['manager3'] = new \stdClass($b); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. * @@ -416,6 +435,34 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container return $instance; } + /** + * Gets the private 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + return $this->privates['mailer.transport'] = (new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->privates['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)))->create(); + } + + /** + * Gets the private 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = new \stdClass(); + + $this->privates['mailer.transport_factory.amazon'] = $instance = new \stdClass($a); + + $a->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the private 'manager4' shared service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php index 4905ade2dd..4540459203 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php @@ -42,9 +42,14 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container 'listener3' => 'getListener3Service', 'listener4' => 'getListener4Service', 'logger' => 'getLoggerService', + 'mailer.transport' => 'getMailer_TransportService', + 'mailer.transport_factory' => 'getMailer_TransportFactoryService', + 'mailer.transport_factory.amazon' => 'getMailer_TransportFactory_AmazonService', 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', + 'monolog.logger_2' => 'getMonolog_Logger2Service', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -434,6 +439,50 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container return $instance; } + /** + * Gets the public 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + $a = ($this->services['mailer.transport_factory'] ?? $this->getMailer_TransportFactoryService()); + + if (isset($this->services['mailer.transport'])) { + return $this->services['mailer.transport']; + } + + return $this->services['mailer.transport'] = $a->create(); + } + + /** + * Gets the public 'mailer.transport_factory' shared service. + * + * @return \FactoryCircular + */ + protected function getMailer_TransportFactoryService() + { + return $this->services['mailer.transport_factory'] = new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->services['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)); + } + + /** + * Gets the public 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = ($this->services['monolog.logger_2'] ?? $this->getMonolog_Logger2Service()); + + if (isset($this->services['mailer.transport_factory.amazon'])) { + return $this->services['mailer.transport_factory.amazon']; + } + + return $this->services['mailer.transport_factory.amazon'] = new \stdClass($a); + } + /** * Gets the public 'manager' shared service. * @@ -482,6 +531,34 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container return $this->services['manager3'] = new \stdClass($a); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + + /** + * Gets the public 'monolog.logger_2' shared service. + * + * @return \stdClass + */ + protected function getMonolog_Logger2Service() + { + $this->services['monolog.logger_2'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. * diff --git a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php index a33490b8ef..a35c131dc3 100644 --- a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php +++ b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php @@ -95,6 +95,10 @@ class TraceableResponse implements ResponseInterface, StreamableInterface if ($this->event && $this->event->isStarted()) { $this->event->stop(); } + + if ($throw) { + $this->checkStatusCode($this->response->getStatusCode()); + } } } @@ -116,6 +120,10 @@ class TraceableResponse implements ResponseInterface, StreamableInterface if ($this->event && $this->event->isStarted()) { $this->event->stop(); } + + if ($throw) { + $this->checkStatusCode($this->response->getStatusCode()); + } } } diff --git a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php index 2ba50adfe2..544f4509c4 100755 --- a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php +++ b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpClient\NativeHttpClient; use Symfony\Component\HttpClient\Response\MockResponse; use Symfony\Component\HttpClient\TraceableHttpClient; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Symfony\Contracts\HttpClient\Test\TestHttpServer; @@ -118,6 +119,18 @@ class TraceableHttpClientTest extends TestCase $this->assertSame('Symfony is awesome!', implode('', $chunks)); } + public function testToArrayChecksStatusCodeBeforeDecoding() + { + $this->expectException(ClientExceptionInterface::class); + + $sut = new TraceableHttpClient(new MockHttpClient($responseFactory = function (): MockResponse { + return new MockResponse('Errored.', ['http_code' => 400]); + })); + + $response = $sut->request('GET', 'https://example.com/foo/bar'); + $response->toArray(); + } + public function testStopwatch() { $sw = new Stopwatch(true); diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php index 218d750b8e..779109039b 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorageInterface.php @@ -30,7 +30,7 @@ interface TokenStorageInterface /** * Sets the authentication token. * - * @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored + * @param TokenInterface|null $token A TokenInterface token, or null if no further authentication information should be stored */ public function setToken(TokenInterface $token = null); } diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.pt.xlf similarity index 100% rename from src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf rename to src/Symfony/Component/Security/Core/Resources/translations/security.pt.xlf