*/
diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php
index 311c41ec66b68..5a1b3300fd33b 100644
--- a/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php
+++ b/src/Symfony/Component/Config/Tests/Definition/Builder/ExprBuilderTest.php
@@ -149,7 +149,7 @@ public function testThenEmptyArrayExpression()
/**
* @dataProvider castToArrayValues
*/
- public function testcastToArrayExpression($configValue, $expectedValue)
+ public function testCastToArrayExpression($configValue, $expectedValue)
{
$test = $this->getTestBuilder()
->castToArray()
diff --git a/src/Symfony/Component/Console/Tests/TerminalTest.php b/src/Symfony/Component/Console/Tests/TerminalTest.php
index f135edf8b0689..c2d36fe0ab899 100644
--- a/src/Symfony/Component/Console/Tests/TerminalTest.php
+++ b/src/Symfony/Component/Console/Tests/TerminalTest.php
@@ -60,7 +60,7 @@ public function test()
$this->assertSame(60, $terminal->getHeight());
}
- public function test_zero_values()
+ public function testZeroValues()
{
putenv('COLUMNS=0');
putenv('LINES=0');
diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md
index 62604dd5debd1..8f1cddfe650a4 100644
--- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md
+++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md
@@ -4,6 +4,7 @@ CHANGELOG
5.1.0
-----
+ * deprecated `inline()` in favor of `inline_service()` and `ref()` in favor of `service()` when using the PHP-DSL
* allow decorators to reference their decorated service using the special `.inner` id
* added support to autowire public typed properties in php 7.4
* added support for defining method calls, a configurator, and property setters in `InlineServiceConfigurator`
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php
index 0d01e2a6f7f0b..f6942c45d9b42 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveHotPathPass.php
@@ -52,14 +52,29 @@ protected function processValue($value, bool $isRoot = false)
if ($value instanceof ArgumentInterface) {
return $value;
}
- if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
- return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
+
+ if ($value instanceof Definition && $isRoot) {
+ if ($value->isDeprecated()) {
+ return $value->clearTag($this->tagName);
+ }
+
+ $this->resolvedIds[$this->currentId] = true;
+
+ if (!$value->hasTag($this->tagName)) {
+ return $value;
+ }
}
- if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) {
- $definition = $this->container->findDefinition($id);
- if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
- $this->resolvedIds[$id] = true;
- $definition->addTag($this->tagName);
+
+ if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->hasDefinition($id = (string) $value)) {
+ $definition = $this->container->getDefinition($id);
+
+ if ($definition->isDeprecated() || $definition->hasTag($this->tagName)) {
+ return $value;
+ }
+
+ $definition->addTag($this->tagName);
+
+ if (isset($this->resolvedIds[$id])) {
parent::processValue($definition, false);
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 5c8bb9c9d34ca..95e91d715564c 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -851,7 +851,7 @@ protected function {$methodName}($lazyInitialization)
if ($definition->isDeprecated()) {
$deprecation = $definition->getDeprecation($id);
$code .= sprintf(" trigger_deprecation(%s, %s, %s);\n\n", $this->export($deprecation['package']), $this->export($deprecation['version']), $this->export($deprecation['message']));
- } elseif (!$definition->hasTag($this->preloadTags[1])) {
+ } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) {
foreach ($this->inlinedDefinitions as $def) {
foreach ($this->getClasses($def, $id) as $class) {
$this->preload[$class] = $class;
@@ -1017,7 +1017,7 @@ private function addServices(array &$services = null): string
foreach ($definitions as $id => $definition) {
if (!$definition->isSynthetic()) {
$services[$id] = $this->addService($id, $definition);
- } elseif (!$definition->hasTag($this->preloadTags[1])) {
+ } elseif ($definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1])) {
$services[$id] = null;
foreach ($this->getClasses($definition, $id) as $class) {
@@ -1046,7 +1046,7 @@ private function generateServiceFiles(array $services): iterable
ksort($definitions);
foreach ($definitions as $id => $definition) {
if ((list($file, $code) = $services[$id]) && null !== $file && ($definition->isPublic() || !$this->isTrivialInstance($definition) || isset($this->locatedIds[$id]))) {
- yield $file => [$code, !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()];
+ yield $file => [$code, $definition->hasTag($this->hotPathTag) || !$definition->hasTag($this->preloadTags[1]) && !$definition->isDeprecated() && !$definition->hasErrors()];
}
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/Preloader.php b/src/Symfony/Component/DependencyInjection/Dumper/Preloader.php
index 7d4c42c46c420..c2c805861be75 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/Preloader.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/Preloader.php
@@ -27,7 +27,7 @@ public static function append(string $file, array $list): void
foreach ($list as $item) {
if (0 === strpos($item, $cacheDir)) {
- file_put_contents($file, sprintf("require __DIR__.%s;\n", var_export(substr($item, \strlen($cacheDir)), true)), FILE_APPEND);
+ file_put_contents($file, sprintf("require_once __DIR__.%s;\n", var_export(substr($item, \strlen($cacheDir)), true)), FILE_APPEND);
continue;
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
index ebec140a93377..16eb471645b8d 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php
@@ -84,20 +84,32 @@ final public function withPath(string $path): self
/**
* Creates a service reference.
+ *
+ * @deprecated since Symfony 5.1, use service() instead.
*/
function ref(string $id): ReferenceConfigurator
{
+ trigger_deprecation('symfony/dependency-injection', '5.1', '"%s()" is deprecated, use "service()" instead.', __FUNCTION__);
+
return new ReferenceConfigurator($id);
}
+/**
+ * Creates a reference to a service.
+ */
+function service(string $serviceId): ReferenceConfigurator
+{
+ return new ReferenceConfigurator($serviceId);
+}
+
/**
* Creates an inline service.
*
- * @deprecated since Symfony 5.1, use service() instead.
+ * @deprecated since Symfony 5.1, use inline_service() instead.
*/
function inline(string $class = null): InlineServiceConfigurator
{
- trigger_deprecation('symfony/dependency-injection', '5.1', '"%s()" is deprecated, use "service()" instead.', __FUNCTION__);
+ trigger_deprecation('symfony/dependency-injection', '5.1', '"%s()" is deprecated, use "inline_service()" instead.', __FUNCTION__);
return new InlineServiceConfigurator(new Definition($class));
}
@@ -105,7 +117,7 @@ function inline(string $class = null): InlineServiceConfigurator
/**
* Creates an inline service.
*/
-function service(string $class = null): InlineServiceConfigurator
+function inline_service(string $class = null): InlineServiceConfigurator
{
return new InlineServiceConfigurator(new Definition($class));
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php
index 3834d72acada1..0b376bf041539 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php
@@ -27,7 +27,7 @@ final public function factory($factory): self
if (\is_string($factory) && 1 === substr_count($factory, ':')) {
$factoryParts = explode(':', $factory);
- throw new InvalidArgumentException(sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[ref(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1]));
+ throw new InvalidArgumentException(sprintf('Invalid factory "%s": the "service:method" notation is not available when using PHP-based DI configuration. Use "[service(\'%s\'), \'%s\']" instead.', $factory, $factoryParts[0], $factoryParts[1]));
}
$this->definition->setFactory(static::processValue($factory, true));
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.php
index 65605bcccff89..de1fe4cec6698 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/anonymous.php
@@ -13,7 +13,7 @@
$s->set(null, StdClassDecorator::class)
->decorate('decorated', 'decorator42')
- ->args([ref('decorator42')]);
+ ->args([service('decorator42')]);
$s->set('listener_aggregator', FooClass::class)->public()->args([tagged_iterator('listener')]);
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php
index 8e0a4a3a0236f..be51444d5e4a9 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php
@@ -7,5 +7,5 @@
return function (ContainerConfigurator $c) {
$s = $c->services()->defaults()->public();
$s->set(BarService::class)
- ->args([service('FooClass')]);
+ ->args([inline_service('FooClass')]);
};
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php
index d2735bcfb1bfb..c9422269c38ab 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php
@@ -15,7 +15,7 @@
->parent(BarService::class)
->public()
->decorate('bar', 'b', 1)
- ->args([ref('b')])
+ ->args([service('b')])
->class('Class2')
->file('file.php')
->parent('bar')
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php
index b04413d2102f3..181ded5323f22 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php
@@ -13,9 +13,9 @@
->autoconfigure()
->autowire()
->tag('t', ['a' => 'b'])
- ->bind(Foo::class, ref('bar'))
+ ->bind(Foo::class, service('bar'))
->public();
- $s->set(Foo::class)->args([ref('bar')])->public();
+ $s->set(Foo::class)->args([service('bar')])->public();
$s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false);
};
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php
index d9f62a67ec9a8..513c8ef26e741 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php
@@ -9,7 +9,7 @@
$s = $c->services()->defaults()->public();
$s->instanceof(Prototype\Foo::class)
->property('p', 0)
- ->call('setFoo', [ref('foo')])
+ ->call('setFoo', [service('foo')])
->tag('tag', ['k' => 'v'])
->share(false)
->lazy()
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/object.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/object.php
index 25a0098af7c00..00ed574df2cb6 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/object.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/object.php
@@ -9,6 +9,6 @@ public function __invoke(ContainerConfigurator $c)
{
$s = $c->services()->defaults()->public();
$s->set(BarService::class)
- ->args([service('FooClass')]);
+ ->args([inline_service('FooClass')]);
}
};
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php
index 98134fb230409..7a0fa86185d08 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php
@@ -11,7 +11,7 @@
;
$c->services()->defaults()->public()
(Foo::class)
- ->arg('$bar', ref('bar'))
+ ->arg('$bar', service('bar'))
->public()
('bar', Foo::class)
->call('setFoo')
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php
index 2d5a1cdc93bac..aa132a4fb6150 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php
@@ -18,16 +18,16 @@
$s = $c->services()->defaults()->public();
$s->set('foo')
- ->args(['foo', ref('foo.baz'), ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'], true, ref('service_container')])
+ ->args(['foo', service('foo.baz'), ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'], true, service('service_container')])
->class(FooClass::class)
->tag('foo', ['foo' => 'foo'])
->tag('foo', ['bar' => 'bar', 'baz' => 'baz'])
->tag('foo', ['name' => 'bar', 'baz' => 'baz'])
->factory([FooClass::class, 'getInstance'])
->property('foo', 'bar')
- ->property('moo', ref('foo.baz'))
+ ->property('moo', service('foo.baz'))
->property('qux', ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'])
- ->call('setBar', [ref('bar')])
+ ->call('setBar', [service('bar')])
->call('initialize')
->configurator('sc_configure');
@@ -36,48 +36,48 @@
->configurator(['%baz_class%', 'configureStatic1']);
$s->set('bar', FooClass::class)
- ->args(['foo', ref('foo.baz'), new Parameter('foo_bar')])
- ->configurator([ref('foo.baz'), 'configure']);
+ ->args(['foo', service('foo.baz'), new Parameter('foo_bar')])
+ ->configurator([service('foo.baz'), 'configure']);
$s->set('foo_bar', '%foo_class%')
- ->args([ref('deprecated_service')])
+ ->args([service('deprecated_service')])
->share(false);
$s->set('method_call1', 'Bar\FooClass')
->file(realpath(__DIR__.'/../includes/foo.php'))
- ->call('setBar', [ref('foo')])
- ->call('setBar', [ref('foo2')->nullOnInvalid()])
- ->call('setBar', [ref('foo3')->ignoreOnInvalid()])
- ->call('setBar', [ref('foobaz')->ignoreOnInvalid()])
+ ->call('setBar', [service('foo')])
+ ->call('setBar', [service('foo2')->nullOnInvalid()])
+ ->call('setBar', [service('foo3')->ignoreOnInvalid()])
+ ->call('setBar', [service('foobaz')->ignoreOnInvalid()])
->call('setBar', [expr('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")')]);
$s->set('foo_with_inline', 'Foo')
- ->call('setBar', [ref('inlined')]);
+ ->call('setBar', [service('inlined')]);
$s->set('inlined', 'Bar')
->property('pub', 'pub')
- ->call('setBaz', [ref('baz')])
+ ->call('setBaz', [service('baz')])
->private();
$s->set('baz', 'Baz')
- ->call('setFoo', [ref('foo_with_inline')]);
+ ->call('setFoo', [service('foo_with_inline')]);
$s->set('request', 'Request')
->synthetic();
$s->set('configurator_service', 'ConfClass')
->private()
- ->call('setFoo', [ref('baz')]);
+ ->call('setFoo', [service('baz')]);
$s->set('configured_service', 'stdClass')
- ->configurator([ref('configurator_service'), 'configureStdClass']);
+ ->configurator([service('configurator_service'), 'configureStdClass']);
$s->set('configurator_service_simple', 'ConfClass')
->args(['bar'])
->private();
$s->set('configured_service_simple', 'stdClass')
- ->configurator([ref('configurator_service_simple'), 'configureStdClass']);
+ ->configurator([service('configurator_service_simple'), 'configureStdClass']);
$s->set('decorated', 'stdClass');
@@ -95,11 +95,11 @@
->private();
$s->set('factory_service', 'Bar')
- ->factory([ref('foo.baz'), 'getInstance']);
+ ->factory([service('foo.baz'), 'getInstance']);
$s->set('new_factory_service', 'FooBarBaz')
->property('foo', 'bar')
- ->factory([ref('new_factory'), 'getInstance']);
+ ->factory([service('new_factory'), 'getInstance']);
$s->set('service_from_static_method', 'Bar\FooClass')
->factory(['Bar\FooClass', 'getInstance']);
@@ -110,15 +110,15 @@
->private();
$s->set('factory_service_simple', 'Bar')
- ->factory([ref('factory_simple'), 'getInstance']);
+ ->factory([service('factory_simple'), 'getInstance']);
$s->set('lazy_context', 'LazyContext')
- ->args([iterator(['k1' => ref('foo.baz'), 'k2' => ref('service_container')]), iterator([])]);
+ ->args([iterator(['k1' => service('foo.baz'), 'k2' => service('service_container')]), iterator([])]);
$s->set('lazy_context_ignore_invalid_ref', 'LazyContext')
- ->args([iterator([ref('foo.baz'), ref('invalid')->ignoreOnInvalid()]), iterator([])]);
+ ->args([iterator([service('foo.baz'), service('invalid')->ignoreOnInvalid()]), iterator([])]);
- $s->set('BAR', 'stdClass')->property('bar', ref('bar'));
+ $s->set('BAR', 'stdClass')->property('bar', service('bar'));
$s->set('bar2', 'stdClass');
$s->set('BAR2', 'stdClass');
@@ -138,5 +138,5 @@
->public();
$s->alias('alias_for_foo', 'foo')->private()->public();
- $s->alias('alias_for_alias', ref('alias_for_foo'));
+ $s->alias('alias_for_alias', service('alias_for_foo'));
};
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/stack.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/stack.php
index 8a4d7ca19a1de..c8ae7a4942013 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/stack.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/stack.php
@@ -8,43 +8,43 @@
$services = $c->services();
$services->stack('stack_a', [
- service('stdClass')
+ inline_service('stdClass')
->property('label', 'A')
- ->property('inner', ref('.inner')),
- service('stdClass')
+ ->property('inner', service('.inner')),
+ inline_service('stdClass')
->property('label', 'B')
- ->property('inner', ref('.inner')),
- service('stdClass')
+ ->property('inner', service('.inner')),
+ inline_service('stdClass')
->property('label', 'C'),
])->public();
$services->stack('stack_abstract', [
- service('stdClass')
+ inline_service('stdClass')
->property('label', 'A')
- ->property('inner', ref('.inner')),
- service('stdClass')
+ ->property('inner', service('.inner')),
+ inline_service('stdClass')
->property('label', 'B')
- ->property('inner', ref('.inner')),
+ ->property('inner', service('.inner')),
]);
$services->stack('stack_b', [
- ref('stack_abstract'),
- service('stdClass')
+ service('stack_abstract'),
+ inline_service('stdClass')
->property('label', 'C'),
])->public();
$services->stack('stack_c', [
- service('stdClass')
+ inline_service('stdClass')
->property('label', 'Z')
- ->property('inner', ref('.inner')),
- ref('stack_a'),
+ ->property('inner', service('.inner')),
+ service('stack_a'),
])->public();
$services->stack('stack_d', [
- service()
+ inline_service()
->parent('stack_abstract')
->property('label', 'Z'),
- service('stdClass')
+ inline_service('stdClass')
->property('label', 'C'),
])->public();
};
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php
index 9b3b6b5ba4e74..3952d6936af0c 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php
@@ -96,7 +96,7 @@ public function testAutoConfigureAndChildDefinition()
public function testFactoryShortNotationNotAllowed()
{
$this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException');
- $this->expectExceptionMessage('Invalid factory "factory:method": the "service:method" notation is not available when using PHP-based DI configuration. Use "[ref(\'factory\'), \'method\']" instead.');
+ $this->expectExceptionMessage('Invalid factory "factory:method": the "service:method" notation is not available when using PHP-based DI configuration. Use "[service(\'factory\'), \'method\']" instead.');
$fixtures = realpath(__DIR__.'/../Fixtures');
$container = new ContainerBuilder();
$loader = new PhpFileLoader($container, new FileLocator());
diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php
index 5147e573ec6cb..c2b8b0d4187e8 100644
--- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php
+++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php
@@ -71,12 +71,12 @@ public function process(ContainerBuilder $container)
return;
}
+ $aliases = [];
+
if ($container->hasParameter($this->eventAliasesParameter)) {
$aliases = $container->getParameter($this->eventAliasesParameter);
- $container->getParameterBag()->remove($this->eventAliasesParameter);
- } else {
- $aliases = [];
}
+
$globalDispatcherDefinition = $container->findDefinition($this->dispatcherService);
foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) {
diff --git a/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php b/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php
index 824f21599c256..741590b1bf3a3 100644
--- a/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php
+++ b/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php
@@ -40,6 +40,9 @@ interface EventSubscriberInterface
* * ['eventName' => ['methodName', $priority]]
* * ['eventName' => [['methodName1', $priority], ['methodName2']]]
*
+ * The code must not depend on runtime state as it will only be called at compile time.
+ * All logic depending on runtime state must be put into the individual methods handling the events.
+ *
* @return array The event names to listen to
*/
public static function getSubscribedEvents();
diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
index 16aade0bc01d0..f557f1f8a6eea 100644
--- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
+++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
@@ -234,17 +234,22 @@ public function testInvokableEventListener()
public function testAliasedEventListener(): void
{
$container = new ContainerBuilder();
- $container->setParameter('event_dispatcher.event_aliases', [AliasedEvent::class => 'aliased_event']);
+ $eventAliases = [AliasedEvent::class => 'aliased_event'];
+ $container->setParameter('event_dispatcher.event_aliases', $eventAliases);
$container->register('foo', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => AliasedEvent::class, 'method' => 'onEvent']);
$container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => CustomEvent::class, 'method' => 'onEvent']);
$container->register('event_dispatcher');
- $eventAliasPass = new AddEventAliasesPass([CustomEvent::class => 'custom_event']);
+ $customEventAlias = [CustomEvent::class => 'custom_event'];
+ $eventAliasPass = new AddEventAliasesPass($customEventAlias);
$eventAliasPass->process($container);
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
+ $this->assertTrue($container->hasParameter('event_dispatcher.event_aliases'));
+ $this->assertSame(array_merge($eventAliases, $customEventAlias), $container->getParameter('event_dispatcher.event_aliases'));
+
$definition = $container->getDefinition('event_dispatcher');
$expectedCalls = [
[
diff --git a/src/Symfony/Component/HttpClient/Chunk/ErrorChunk.php b/src/Symfony/Component/HttpClient/Chunk/ErrorChunk.php
index c3df62ce32695..f91f2bdf528ea 100644
--- a/src/Symfony/Component/HttpClient/Chunk/ErrorChunk.php
+++ b/src/Symfony/Component/HttpClient/Chunk/ErrorChunk.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\HttpClient\Chunk;
+use Symfony\Component\HttpClient\Exception\TimeoutException;
use Symfony\Component\HttpClient\Exception\TransportException;
use Symfony\Contracts\HttpClient\ChunkInterface;
@@ -61,7 +62,7 @@ public function isTimeout(): bool
public function isFirst(): bool
{
$this->didThrow = true;
- throw new TransportException($this->errorMessage, 0, $this->error);
+ throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
}
/**
@@ -70,7 +71,7 @@ public function isFirst(): bool
public function isLast(): bool
{
$this->didThrow = true;
- throw new TransportException($this->errorMessage, 0, $this->error);
+ throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
}
/**
@@ -79,7 +80,7 @@ public function isLast(): bool
public function getInformationalStatus(): ?array
{
$this->didThrow = true;
- throw new TransportException($this->errorMessage, 0, $this->error);
+ throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
}
/**
@@ -88,7 +89,7 @@ public function getInformationalStatus(): ?array
public function getContent(): string
{
$this->didThrow = true;
- throw new TransportException($this->errorMessage, 0, $this->error);
+ throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
}
/**
@@ -119,7 +120,7 @@ public function __destruct()
{
if (!$this->didThrow) {
$this->didThrow = true;
- throw new TransportException($this->errorMessage, 0, $this->error);
+ throw null !== $this->error ? new TransportException($this->errorMessage, 0, $this->error) : new TimeoutException($this->errorMessage);
}
}
}
diff --git a/src/Symfony/Component/HttpClient/Exception/TimeoutException.php b/src/Symfony/Component/HttpClient/Exception/TimeoutException.php
new file mode 100644
index 0000000000000..a9155cc8f612c
--- /dev/null
+++ b/src/Symfony/Component/HttpClient/Exception/TimeoutException.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\HttpClient\Exception;
+
+use Symfony\Contracts\HttpClient\Exception\TimeoutExceptionInterface;
+
+/**
+ * @author Nicolas Grekas
+ */
+final class TimeoutException extends TransportException implements TimeoutExceptionInterface
+{
+}
diff --git a/src/Symfony/Component/HttpClient/Exception/TransportException.php b/src/Symfony/Component/HttpClient/Exception/TransportException.php
index 117e2976268ec..a3a80c6dc64e4 100644
--- a/src/Symfony/Component/HttpClient/Exception/TransportException.php
+++ b/src/Symfony/Component/HttpClient/Exception/TransportException.php
@@ -16,6 +16,6 @@
/**
* @author Nicolas Grekas
*/
-final class TransportException extends \RuntimeException implements TransportExceptionInterface
+class TransportException extends \RuntimeException implements TransportExceptionInterface
{
}
diff --git a/src/Symfony/Component/HttpClient/Response/AmpResponse.php b/src/Symfony/Component/HttpClient/Response/AmpResponse.php
index e5d0bb213fc8a..c553dad6dec6c 100644
--- a/src/Symfony/Component/HttpClient/Response/AmpResponse.php
+++ b/src/Symfony/Component/HttpClient/Response/AmpResponse.php
@@ -200,7 +200,7 @@ private static function generateResponse(Request $request, AmpClientState $multi
$options = null;
- $activity[$id] = [new FirstChunk()];
+ $activity[$id][] = new FirstChunk();
if ('HEAD' === $response->getRequest()->getMethod() || \in_array($info['http_code'], [204, 304], true)) {
$activity[$id][] = null;
diff --git a/src/Symfony/Component/HttpClient/Response/CurlResponse.php b/src/Symfony/Component/HttpClient/Response/CurlResponse.php
index 58528108e8d1a..80709ed8a6a76 100644
--- a/src/Symfony/Component/HttpClient/Response/CurlResponse.php
+++ b/src/Symfony/Component/HttpClient/Response/CurlResponse.php
@@ -312,8 +312,15 @@ private static function parseHeaderLine($ch, string $data, array &$info, array &
}
if ("\r\n" !== $data) {
- // Regular header line: add it to the list
- self::addResponseHeaders([substr($data, 0, -2)], $info, $headers);
+ try {
+ // Regular header line: add it to the list
+ self::addResponseHeaders([substr($data, 0, -2)], $info, $headers);
+ } catch (TransportException $e) {
+ $multi->handlesActivity[$id][] = null;
+ $multi->handlesActivity[$id][] = $e;
+
+ return \strlen($data);
+ }
if (0 !== strpos($data, 'HTTP/')) {
if (0 === stripos($data, 'Location:')) {
diff --git a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
index efc3928f4ab32..44f2b559795c8 100644
--- a/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
+++ b/src/Symfony/Component/HttpClient/Response/ResponseTrait.php
@@ -253,7 +253,7 @@ private static function initialize(self $response): void
private static function addResponseHeaders(array $responseHeaders, array &$info, array &$headers, string &$debug = ''): void
{
foreach ($responseHeaders as $h) {
- if (11 <= \strlen($h) && '/' === $h[4] && preg_match('#^HTTP/\d+(?:\.\d+)? ([12345]\d\d)(?: |$)#', $h, $m)) {
+ if (11 <= \strlen($h) && '/' === $h[4] && preg_match('#^HTTP/\d+(?:\.\d+)? ([1-9]\d\d)(?: |$)#', $h, $m)) {
if ($headers) {
$debug .= "< \r\n";
$headers = [];
diff --git a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php
index 9305e9be942d0..2fe78f45748bc 100644
--- a/src/Symfony/Component/HttpClient/Response/TraceableResponse.php
+++ b/src/Symfony/Component/HttpClient/Response/TraceableResponse.php
@@ -14,6 +14,7 @@
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpClient\Exception\RedirectionException;
use Symfony\Component\HttpClient\Exception\ServerException;
+use Symfony\Component\HttpClient\TraceableHttpClient;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
@@ -105,6 +106,28 @@ public function toStream(bool $throw = true)
return StreamWrapper::createResource($this->response, $this->client);
}
+ /**
+ * @internal
+ */
+ public static function stream(HttpClientInterface $client, iterable $responses, ?float $timeout): \Generator
+ {
+ $wrappedResponses = [];
+ $traceableMap = new \SplObjectStorage();
+
+ foreach ($responses as $r) {
+ if (!$r instanceof self) {
+ throw new \TypeError(sprintf('"%s::stream()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', TraceableHttpClient::class, get_debug_type($r)));
+ }
+
+ $traceableMap[$r->response] = $r;
+ $wrappedResponses[] = $r->response;
+ }
+
+ foreach ($client->stream($wrappedResponses, $timeout) as $r => $chunk) {
+ yield $traceableMap[$r] => $chunk;
+ }
+ }
+
private function checkStatusCode($code)
{
if (500 <= $code) {
diff --git a/src/Symfony/Component/HttpClient/Tests/AmpHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/AmpHttpClientTest.php
index c3bdbed0aa8b0..e17b45a0ce185 100644
--- a/src/Symfony/Component/HttpClient/Tests/AmpHttpClientTest.php
+++ b/src/Symfony/Component/HttpClient/Tests/AmpHttpClientTest.php
@@ -25,13 +25,4 @@ public function testProxy()
{
$this->markTestSkipped('A real proxy server would be needed.');
}
-
- public function testInformationalResponseStream()
- {
- if (getenv('TRAVIS_PULL_REQUEST')) {
- $this->markTestIncomplete('This test always fails on Travis.');
- }
-
- parent::testInformationalResponseStream();
- }
}
diff --git a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
index 966971823e8c6..7c9a1aa3c6da6 100644
--- a/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
+++ b/src/Symfony/Component/HttpClient/Tests/MockHttpClientTest.php
@@ -253,6 +253,7 @@ protected function getHttpClient(string $testCase): HttpClientInterface
case 'testTimeoutOnStream':
case 'testUncheckedTimeoutThrows':
+ case 'testTimeoutIsNotAFatalError':
$body = ['<1>', '', '<2>'];
$responses[] = new MockResponse($body, ['response_headers' => $headers]);
break;
diff --git a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php
index 66097d013bafb..8c0ec0d48cc5a 100755
--- a/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php
+++ b/src/Symfony/Component/HttpClient/Tests/TraceableHttpClientTest.php
@@ -88,11 +88,12 @@ public function testStream()
TestHttpServer::start();
$sut = new TraceableHttpClient(new NativeHttpClient());
- $chunked = $sut->request('GET', 'http://localhost:8057/chunked');
+ $response = $sut->request('GET', 'http://localhost:8057/chunked');
$chunks = [];
- foreach ($sut->stream($chunked) as $response) {
- $chunks[] = $response->getContent();
+ foreach ($sut->stream($response) as $r => $chunk) {
+ $chunks[] = $chunk->getContent();
}
+ $this->assertSame($response, $r);
$this->assertGreaterThan(1, \count($chunks));
$this->assertSame('Symfony is awesome!', implode('', $chunks));
}
diff --git a/src/Symfony/Component/HttpClient/TraceableHttpClient.php b/src/Symfony/Component/HttpClient/TraceableHttpClient.php
index f7fbfafc3b0c7..b70c544a66b6f 100644
--- a/src/Symfony/Component/HttpClient/TraceableHttpClient.php
+++ b/src/Symfony/Component/HttpClient/TraceableHttpClient.php
@@ -13,6 +13,7 @@
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpClient\Response\ResponseStream;
use Symfony\Component\HttpClient\Response\TraceableResponse;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
@@ -70,15 +71,7 @@ public function stream($responses, float $timeout = null): ResponseStreamInterfa
throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
}
- return $this->client->stream(\Closure::bind(static function () use ($responses) {
- foreach ($responses as $k => $r) {
- if (!$r instanceof TraceableResponse) {
- throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', __METHOD__, get_debug_type($r)));
- }
-
- yield $k => $r->response;
- }
- }, null, TraceableResponse::class)(), $timeout);
+ return new ResponseStream(TraceableResponse::stream($this->client, $responses, $timeout));
}
public function getTracedRequests(): array
diff --git a/src/Symfony/Component/HttpClient/composer.json b/src/Symfony/Component/HttpClient/composer.json
index 75cccf6717726..1b7ac6efd9d71 100644
--- a/src/Symfony/Component/HttpClient/composer.json
+++ b/src/Symfony/Component/HttpClient/composer.json
@@ -23,7 +23,7 @@
"require": {
"php": "^7.2.5",
"psr/log": "^1.0",
- "symfony/http-client-contracts": "^1.1.8|^2",
+ "symfony/http-client-contracts": "^2.1.1",
"symfony/polyfill-php73": "^1.11",
"symfony/polyfill-php80": "^1.15",
"symfony/service-contracts": "^1.0|^2"
diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
index 5acefc9c969e0..76e11ce36e5c5 100644
--- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
+++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
@@ -286,8 +286,6 @@ protected function computeCacheControlValue()
private function initDate(): void
{
- $now = \DateTime::createFromFormat('U', time());
- $now->setTimezone(new \DateTimeZone('UTC'));
- $this->set('Date', $now->format('D, d M Y H:i:s').' GMT');
+ $this->set('Date', gmdate('D, d M Y H:i:s').' GMT');
}
}
diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php
index 3143f2b9a60b7..8fd17adc7d0f9 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php
@@ -119,7 +119,7 @@ public function onKernelTerminate(TerminateEvent $event)
public static function getSubscribedEvents(): array
{
return [
- KernelEvents::RESPONSE => ['onKernelResponse', -100],
+ KernelEvents::RESPONSE => ['onKernelResponse', -1012],
KernelEvents::EXCEPTION => ['onKernelException', 0],
KernelEvents::TERMINATE => ['onKernelTerminate', -1024],
];
diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php
index 738f913886273..163e1120771c9 100644
--- a/src/Symfony/Component/HttpKernel/Kernel.php
+++ b/src/Symfony/Component/HttpKernel/Kernel.php
@@ -73,12 +73,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
private static $freshCache = [];
- const VERSION = '5.1.0-BETA1';
+ const VERSION = '5.1.0-RC1';
const VERSION_ID = 50100;
const MAJOR_VERSION = 5;
const MINOR_VERSION = 1;
const RELEASE_VERSION = 0;
- const EXTRA_VERSION = 'BETA1';
+ const EXTRA_VERSION = 'RC1';
const END_OF_MAINTENANCE = '01/2021';
const END_OF_LIFE = '01/2021';
diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json
index 7373a93bac2b1..3fa828c0fc73f 100644
--- a/src/Symfony/Component/Inflector/composer.json
+++ b/src/Symfony/Component/Inflector/composer.json
@@ -25,7 +25,6 @@
"require": {
"php": "^7.2.5",
"symfony/deprecation-contracts": "^2.1",
- "symfony/polyfill-ctype": "~1.8",
"symfony/string": "^5.1"
},
"autoload": {
diff --git a/src/Symfony/Component/Lock/Tests/Store/MongoDbStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/MongoDbStoreTest.php
index 66411c4507af1..1eae5dda750bf 100644
--- a/src/Symfony/Component/Lock/Tests/Store/MongoDbStoreTest.php
+++ b/src/Symfony/Component/Lock/Tests/Store/MongoDbStoreTest.php
@@ -23,6 +23,7 @@
* @author Joe Bennett
*
* @requires function \MongoDB\Client::__construct
+ * @group integration
*/
class MongoDbStoreTest extends AbstractStoreTest
{
diff --git a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php
index 8ea1e717c6ee5..cf537a4c24900 100644
--- a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php
+++ b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php
@@ -48,7 +48,7 @@ public function testResourceRemoval()
private function getOpenedSemaphores()
{
if ('Darwin' === PHP_OS) {
- $lines = explode(PHP_EOL, trim(`ipcs -s`));
+ $lines = explode(PHP_EOL, trim(shell_exec('ipcs -s')));
if (-1 === $start = array_search('Semaphores:', $lines)) {
throw new \Exception('Failed to extract list of opened semaphores. Expected a Semaphore list, got '.implode(PHP_EOL, $lines));
}
@@ -56,7 +56,7 @@ private function getOpenedSemaphores()
return \count(\array_slice($lines, ++$start));
}
- $lines = explode(PHP_EOL, trim(`LC_ALL=C ipcs -su`));
+ $lines = explode(PHP_EOL, trim(shell_exec('LC_ALL=C ipcs -su')));
if ('------ Semaphore Status --------' !== $lines[0]) {
throw new \Exception('Failed to extract list of opened semaphores. Expected a Semaphore status, got '.implode(PHP_EOL, $lines));
}
diff --git a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
index 9d32bc12a3397..e67b17ecb9055 100644
--- a/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
+++ b/src/Symfony/Component/Mailer/Bridge/Mailchimp/Transport/MandrillHttpTransport.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\Mailer\Bridge\Mailchimp\Transport;
use Psr\Log\LoggerInterface;
-use Symfony\Component\Mailer\Envelope;
use Symfony\Component\Mailer\Exception\HttpTransportException;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractHttpTransport;
diff --git a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsIntegrationTest.php b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsIntegrationTest.php
index 251c821a07d5e..3c47be5614751 100644
--- a/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsIntegrationTest.php
+++ b/src/Symfony/Component/Messenger/Bridge/AmazonSqs/Tests/Transport/AmazonSqsIntegrationTest.php
@@ -16,6 +16,9 @@
use Symfony\Component\Messenger\Bridge\AmazonSqs\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Bridge\AmazonSqs\Transport\Connection;
+/**
+ * @group integration
+ */
class AmazonSqsIntegrationTest extends TestCase
{
public function testConnectionSendToFifoQueueAndGet(): void
diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php
index 2f0971a6098e8..97d2f7672f3b8 100644
--- a/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php
+++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Transport/Connection.php
@@ -412,7 +412,7 @@ public function get(string $queueName): ?\AMQPEnvelope
// If we get a 404 for the queue, it means we need to set up the exchange & queue.
$this->setupExchangeAndQueues();
- return $this->get();
+ return $this->get($queueName);
}
throw $e;
diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/composer.json b/src/Symfony/Component/Messenger/Bridge/Amqp/composer.json
index 0522064e2691c..ba1aa2d8fe8f2 100644
--- a/src/Symfony/Component/Messenger/Bridge/Amqp/composer.json
+++ b/src/Symfony/Component/Messenger/Bridge/Amqp/composer.json
@@ -20,10 +20,10 @@
"symfony/messenger": "^5.1"
},
"require-dev": {
- "symfony/property-access": "^4.4|^5.0",
- "symfony/serializer": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0",
- "symfony/process": "^4.4|^5.0"
+ "symfony/process": "^4.4|^5.0",
+ "symfony/property-access": "^4.4|^5.0",
+ "symfony/serializer": "^4.4|^5.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Messenger\\Bridge\\Amqp\\": "" },
diff --git a/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json b/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json
index b2c7b983798c3..52fa0c68a628d 100644
--- a/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json
+++ b/src/Symfony/Component/Messenger/Bridge/Doctrine/composer.json
@@ -17,15 +17,15 @@
],
"require": {
"php": "^7.2.5",
- "doctrine/dbal": "^2.6",
- "doctrine/persistence": "^1.3",
"symfony/messenger": "^5.1",
"symfony/service-contracts": "^1.1|^2"
},
"require-dev": {
+ "doctrine/dbal": "^2.6",
"doctrine/orm": "^2.6.3",
- "symfony/serializer": "^4.4|^5.0",
- "symfony/property-access": "^4.4|^5.0"
+ "doctrine/persistence": "^1.3",
+ "symfony/property-access": "^4.4|^5.0",
+ "symfony/serializer": "^4.4|^5.0"
},
"conflict": {
"doctrine/persistence": "<1.3"
diff --git a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
index 8dfcbe240fe81..1fac374096f59 100644
--- a/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
+++ b/src/Symfony/Component/Messenger/Command/ConsumeMessagesCommand.php
@@ -84,7 +84,7 @@ protected function configure(): void
Use the --limit option to limit the number of messages received:
php %command.full_name% --limit=10
-
+
Use the --failure-limit option to stop the worker when the given number of failed messages is reached:
php %command.full_name% --failure-limit=2
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
index 7fccbac42f079..951b7d499ed1b 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesRemoveCommand.php
@@ -39,7 +39,7 @@ protected function configure(): void
new InputOption('force', null, InputOption::VALUE_NONE, 'Force the operation without confirmation'),
new InputOption('show-messages', null, InputOption::VALUE_NONE, 'Display messages before removing it (if multiple ids are given)'),
])
- ->setDescription('Remove given messages from the failure transport.')
+ ->setDescription('Remove given messages from the failure transport')
->setHelp(<<<'EOF'
The %command.name% removes given messages that are pending in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
index 696e77f7f1949..87426edd9dbaa 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesRetryCommand.php
@@ -59,7 +59,7 @@ protected function configure(): void
new InputArgument('id', InputArgument::IS_ARRAY, 'Specific message id(s) to retry'),
new InputOption('force', null, InputOption::VALUE_NONE, 'Force action without confirmation'),
])
- ->setDescription('Retries one or more messages from the failure transport.')
+ ->setDescription('Retries one or more messages from the failure transport')
->setHelp(<<<'EOF'
The %command.name% retries message in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php b/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
index bcb6911632152..0baf7a419f190 100644
--- a/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
+++ b/src/Symfony/Component/Messenger/Command/FailedMessagesShowCommand.php
@@ -37,7 +37,7 @@ protected function configure(): void
new InputArgument('id', InputArgument::OPTIONAL, 'Specific message id to show'),
new InputOption('max', null, InputOption::VALUE_REQUIRED, 'Maximum number of messages to list', 50),
])
- ->setDescription('Shows one or more messages from the failure transport.')
+ ->setDescription('Shows one or more messages from the failure transport')
->setHelp(<<<'EOF'
The %command.name% shows message that are pending in the failure transport.
diff --git a/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php b/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
index 21916f2be765e..84395892fdf9b 100644
--- a/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
+++ b/src/Symfony/Component/Messenger/Command/SetupTransportsCommand.php
@@ -41,6 +41,7 @@ protected function configure()
{
$this
->addArgument('transport', InputArgument::OPTIONAL, 'Name of the transport to setup', null)
+ ->setDescription('Prepares the required infrastructure for the transport')
->setHelp(<<%command.name% command setups the transports:
diff --git a/src/Symfony/Component/Mime/MimeTypes.php b/src/Symfony/Component/Mime/MimeTypes.php
index dfdea060e466d..c4222b3cfee30 100644
--- a/src/Symfony/Component/Mime/MimeTypes.php
+++ b/src/Symfony/Component/Mime/MimeTypes.php
@@ -51,7 +51,7 @@ public function __construct(array $map = [])
$this->extensions[$mimeType] = $extensions;
foreach ($extensions as $extension) {
- $this->mimeTypes[$extension] = $mimeType;
+ $this->mimeTypes[$extension][] = $mimeType;
}
}
$this->registerGuesser(new FileBinaryMimeTypeGuesser());
diff --git a/src/Symfony/Component/Mime/Test/Constraint/EmailAddressContains.php b/src/Symfony/Component/Mime/Test/Constraint/EmailAddressContains.php
index 58ef360c5021e..c751c3d45f3b5 100644
--- a/src/Symfony/Component/Mime/Test/Constraint/EmailAddressContains.php
+++ b/src/Symfony/Component/Mime/Test/Constraint/EmailAddressContains.php
@@ -48,7 +48,7 @@ protected function matches($message): bool
$header = $message->getHeaders()->get($this->headerName);
if ($header instanceof MailboxHeader) {
- return $this->expectedValue === $header->Address()->getAddress();
+ return $this->expectedValue === $header->getAddress()->getAddress();
} elseif ($header instanceof MailboxListHeader) {
foreach ($header->getAddresses() as $address) {
if ($this->expectedValue === $address->getAddress()) {
diff --git a/src/Symfony/Component/Mime/Tests/MimeTypesTest.php b/src/Symfony/Component/Mime/Tests/MimeTypesTest.php
index a736dbebbae0f..b1387c9a5cda3 100644
--- a/src/Symfony/Component/Mime/Tests/MimeTypesTest.php
+++ b/src/Symfony/Component/Mime/Tests/MimeTypesTest.php
@@ -62,4 +62,15 @@ public function testGetMimeTypes()
$this->assertContains('image/svg', $mt->getMimeTypes('svg'));
$this->assertSame([], $mt->getMimeTypes('symfony'));
}
+
+ public function testCustomMimeTypes()
+ {
+ $mt = new MimeTypes([
+ 'text/bar' => ['foo'],
+ 'text/baz' => ['foo', 'moof'],
+ ]);
+ $this->assertContains('text/bar', $mt->getMimeTypes('foo'));
+ $this->assertContains('text/baz', $mt->getMimeTypes('foo'));
+ $this->assertSame(['foo', 'moof'], $mt->getExtensions('text/baz'));
+ }
}
diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md
index e950032a5c5ec..b54399022bb09 100644
--- a/src/Symfony/Component/Security/CHANGELOG.md
+++ b/src/Symfony/Component/Security/CHANGELOG.md
@@ -11,6 +11,7 @@ CHANGELOG
* Deprecated `LogoutSuccessHandlerInterface` and `LogoutHandlerInterface` in favor of listening on the `LogoutEvent`.
* Added experimental new security using `Http\Authenticator\AuthenticatorInterface`, `Http\Authentication\AuthenticatorManager` and `Http\Firewall\AuthenticatorManagerListener`.
* Added `CustomUserMessageAccountStatusException` to be used when extending `UserCheckerInterface`
+ * Deprecated `RememberMeServicesInterface` implementations without `logout(Request $request, Response $response, TokenInterface $token)` method, this method will be required in Symfony 6.0.
5.0.0
-----
diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
index b9eaa68246076..eefe75d2d3ae5 100644
--- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
+++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php
@@ -26,7 +26,6 @@ class UsernamePasswordToken extends AbstractToken
/**
* @param string|\Stringable|UserInterface $user The username (like a nickname, email address, etc.) or a UserInterface instance
* @param mixed $credentials
- * @param string $providerKey
* @param string[] $roles
*
* @throws \InvalidArgumentException
diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
index 28b7f3b7fdade..8356c38bb93fc 100644
--- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
+++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php
@@ -61,7 +61,7 @@ public function __construct(iterable $voters = [], string $strategy = self::STRA
*/
public function decide(TokenInterface $token, array $attributes, $object = null/*, bool $allowMultipleAttributes = false*/)
{
- $allowMultipleAttributes = 3 < func_num_args() && func_get_arg(3);
+ $allowMultipleAttributes = 3 < \func_num_args() && func_get_arg(3);
// Special case for AccessListener, do not remove the right side of the condition before 6.0
if (\count($attributes) > 1 && !$allowMultipleAttributes) {
diff --git a/src/Symfony/Component/Security/Core/Encoder/NativePasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/NativePasswordEncoder.php
index b2e76c5b46f12..b678801f5efd9 100644
--- a/src/Symfony/Component/Security/Core/Encoder/NativePasswordEncoder.php
+++ b/src/Symfony/Component/Security/Core/Encoder/NativePasswordEncoder.php
@@ -24,7 +24,7 @@ final class NativePasswordEncoder implements PasswordEncoderInterface, SelfSalti
{
private const MAX_PASSWORD_LENGTH = 4096;
- private $algo;
+ private $algo = PASSWORD_BCRYPT;
private $options;
/**
@@ -48,7 +48,20 @@ public function __construct(int $opsLimit = null, int $memLimit = null, int $cos
throw new \InvalidArgumentException('$cost must be in the range of 4-31.');
}
- $this->algo = (string) ($algo ?? (\defined('PASSWORD_ARGON2ID') ? PASSWORD_ARGON2ID : (\defined('PASSWORD_ARGON2I') ? PASSWORD_ARGON2I : PASSWORD_BCRYPT)));
+ $algos = [1 => PASSWORD_BCRYPT, '2y' => PASSWORD_BCRYPT];
+
+ if (\defined('PASSWORD_ARGON2I')) {
+ $this->algo = $algos[2] = $algos['argon2i'] = (string) PASSWORD_ARGON2I;
+ }
+
+ if (\defined('PASSWORD_ARGON2ID')) {
+ $this->algo = $algos[3] = $algos['argon2id'] = (string) PASSWORD_ARGON2ID;
+ }
+
+ if (null !== $algo) {
+ $this->algo = $algos[$algo] ?? $algo;
+ }
+
$this->options = [
'cost' => $cost,
'time_cost' => $opsLimit,
diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
index 6d6eac971ff06..e454852ddf358 100644
--- a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php
@@ -54,10 +54,16 @@ public function testAuthenticateWhenNoProviderSupportsToken()
public function testAuthenticateWhenProviderReturnsAccountStatusException()
{
+ $secondAuthenticationProvider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock();
+
$manager = new AuthenticationProviderManager([
$this->getAuthenticationProvider(true, null, 'Symfony\Component\Security\Core\Exception\AccountStatusException'),
+ $secondAuthenticationProvider,
]);
+ // AccountStatusException stops authentication
+ $secondAuthenticationProvider->expects($this->never())->method('supports');
+
try {
$manager->authenticate($token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
$this->fail();
diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/NativePasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/NativePasswordEncoderTest.php
index 47b8ac09eaa69..9388e9c2c53cc 100644
--- a/src/Symfony/Component/Security/Core/Tests/Encoder/NativePasswordEncoderTest.php
+++ b/src/Symfony/Component/Security/Core/Tests/Encoder/NativePasswordEncoderTest.php
@@ -73,6 +73,14 @@ public function testConfiguredAlgorithm()
$this->assertStringStartsWith('$2', $result);
}
+ public function testConfiguredAlgorithmWithLegacyConstValue()
+ {
+ $encoder = new NativePasswordEncoder(null, null, null, '1');
+ $result = $encoder->encodePassword('password', null);
+ $this->assertTrue($encoder->isPasswordValid($result, 'password', null));
+ $this->assertStringStartsWith('$2', $result);
+ }
+
public function testCheckPasswordLength()
{
$encoder = new NativePasswordEncoder(null, null, 4);
diff --git a/src/Symfony/Component/Security/Http/Authentication/NoopAuthenticationManager.php b/src/Symfony/Component/Security/Http/Authentication/NoopAuthenticationManager.php
index 9e75ff9998c01..7be2e221037bd 100644
--- a/src/Symfony/Component/Security/Http/Authentication/NoopAuthenticationManager.php
+++ b/src/Symfony/Component/Security/Http/Authentication/NoopAuthenticationManager.php
@@ -29,5 +29,6 @@ class NoopAuthenticationManager implements AuthenticationManagerInterface
{
public function authenticate(TokenInterface $token)
{
+ return $token;
}
}
diff --git a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php
index 31cab7afcd35b..201eab349ded4 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/FormLoginAuthenticator.php
@@ -100,7 +100,7 @@ public function authenticate(Request $request): PassportInterface
/**
* @param Passport $passport
*/
- public function createAuthenticatedToken(PassportInterface $passport, $firewallName): TokenInterface
+ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles());
}
diff --git a/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php b/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php
index e4c7af251e8c0..7a70ddc9f37d2 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/HttpBasicAuthenticator.php
@@ -47,7 +47,7 @@ public function __construct(string $realmName, UserProviderInterface $userProvid
$this->logger = $logger;
}
- public function start(Request $request, AuthenticationException $authException = null)
+ public function start(Request $request, AuthenticationException $authException = null): Response
{
$response = new Response();
$response->headers->set('WWW-Authenticate', sprintf('Basic realm="%s"', $this->realmName));
@@ -82,12 +82,12 @@ public function authenticate(Request $request): PassportInterface
/**
* @param Passport $passport
*/
- public function createAuthenticatedToken(PassportInterface $passport, $firewallName): TokenInterface
+ public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles());
}
- public function onAuthenticationSuccess(Request $request, TokenInterface $token, $firewallName): ?Response
+ public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
return null;
}
diff --git a/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportTrait.php b/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportTrait.php
index 1cdd75546bb71..f338c9f304a39 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportTrait.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/Passport/PassportTrait.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\Security\Http\Authenticator\Passport;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
-use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
/**
diff --git a/src/Symfony/Component/Security/Http/Authenticator/Passport/SelfValidatingPassport.php b/src/Symfony/Component/Security/Http/Authenticator/Passport/SelfValidatingPassport.php
index dd3ef6f962181..597351a85f7d4 100644
--- a/src/Symfony/Component/Security/Http/Authenticator/Passport/SelfValidatingPassport.php
+++ b/src/Symfony/Component/Security/Http/Authenticator/Passport/SelfValidatingPassport.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Http\Authenticator\Passport;
use Symfony\Component\Security\Core\User\UserInterface;
+use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;
/**
* An implementation used when there are no credentials to be checked (e.g.
@@ -23,6 +24,9 @@
*/
class SelfValidatingPassport extends Passport
{
+ /**
+ * @param BadgeInterface[] $badges
+ */
public function __construct(UserInterface $user, array $badges = [])
{
$this->user = $user;
diff --git a/src/Symfony/Component/Security/Http/EventListener/RememberMeLogoutListener.php b/src/Symfony/Component/Security/Http/EventListener/RememberMeLogoutListener.php
index 5fbd94b1a90af..50c5df6caab69 100644
--- a/src/Symfony/Component/Security/Http/EventListener/RememberMeLogoutListener.php
+++ b/src/Symfony/Component/Security/Http/EventListener/RememberMeLogoutListener.php
@@ -14,7 +14,7 @@
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Exception\LogicException;
use Symfony\Component\Security\Http\Event\LogoutEvent;
-use Symfony\Component\Security\Http\RememberMe\AbstractRememberMeServices;
+use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/**
* @author Wouter de Jong
@@ -25,13 +25,21 @@ class RememberMeLogoutListener implements EventSubscriberInterface
{
private $rememberMeServices;
- public function __construct(AbstractRememberMeServices $rememberMeServices)
+ public function __construct(RememberMeServicesInterface $rememberMeServices)
{
+ if (!method_exists($rememberMeServices, 'logout')) {
+ trigger_deprecation('symfony/security-core', '5.1', '"%s" should implement the "logout(Request $request, Response $response, TokenInterface $token)" method, this method will be added to the "%s" in version 6.0.', \get_class($rememberMeServices), RememberMeServicesInterface::class);
+ }
+
$this->rememberMeServices = $rememberMeServices;
}
public function onLogout(LogoutEvent $event): void
{
+ if (!method_exists($this->rememberMeServices, 'logout')) {
+ return;
+ }
+
if (null === $event->getResponse()) {
throw new LogicException(sprintf('No response was set for this logout action. Make sure the DefaultLogoutListener or another listener has set the response before "%s" is called.', __CLASS__));
}
diff --git a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php
index ae52591da0ad1..23fc0fc18795a 100644
--- a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php
+++ b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php
@@ -24,6 +24,8 @@
* - PersistentTokenBasedRememberMeServices (requires a TokenProvider)
*
* @author Johannes M. Schmitt
+ *
+ * @method logout(Request $request, Response $response, TokenInterface $token)
*/
interface RememberMeServicesInterface
{
diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
index dfa778cfbac47..713f6fd0d47d3 100644
--- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
+++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php
@@ -411,12 +411,21 @@ protected function instantiateObject(array &$data, string $class, array &$contex
protected function denormalizeParameter(\ReflectionClass $class, \ReflectionParameter $parameter, string $parameterName, $parameterData, array $context, string $format = null)
{
try {
- if (null !== $parameter->getClass()) {
+ if (\PHP_VERSION_ID < 70100 && null !== $parameterClass = $parameter->getClass()) {
+ $parameterClass = $parameterClass->name;
+ } elseif (\PHP_VERSION_ID >= 70100 && $parameter->hasType() && ($parameterType = $parameter->getType()) && !$parameterType->isBuiltin()) {
+ $parameterClass = $parameterType->getName();
+ new \ReflectionClass($parameterClass); // throws a \ReflectionException if the class doesn't exist
+ } else {
+ $parameterClass = null;
+ }
+
+ if (null !== $parameterClass) {
if (!$this->serializer instanceof DenormalizerInterface) {
- throw new LogicException(sprintf('Cannot create an instance of "%s" from serialized data because the serializer inject in "%s" is not a denormalizer.', $parameter->getClass(), self::class));
+ throw new LogicException(sprintf('Cannot create an instance of "%s" from serialized data because the serializer inject in "%s" is not a denormalizer.', $parameterClass, static::class));
}
- $parameterClass = $parameter->getClass()->getName();
- $parameterData = $this->serializer->denormalize($parameterData, $parameterClass, $format, $this->createChildContext($context, $parameterName, $format));
+
+ return $this->serializer->denormalize($parameterData, $parameterClass, $format, $this->createChildContext($context, $parameterName, $format));
}
} catch (\ReflectionException $e) {
throw new RuntimeException(sprintf('Could not determine the class of the parameter "%s".', $parameterName), 0, $e);
@@ -424,7 +433,8 @@ protected function denormalizeParameter(\ReflectionClass $class, \ReflectionPara
if (!$parameter->getType()->allowsNull()) {
throw $e;
}
- $parameterData = null;
+
+ return null;
}
return $parameterData;
diff --git a/src/Symfony/Component/String/Tests/FunctionsTest.php b/src/Symfony/Component/String/Tests/FunctionsTest.php
index ec1c6bb4c0ccb..1f2776e8896de 100644
--- a/src/Symfony/Component/String/Tests/FunctionsTest.php
+++ b/src/Symfony/Component/String/Tests/FunctionsTest.php
@@ -14,8 +14,8 @@
use PHPUnit\Framework\TestCase;
use Symfony\Component\String\AbstractString;
use Symfony\Component\String\ByteString;
-use function Symfony\Component\String\s;
use Symfony\Component\String\UnicodeString;
+use function Symfony\Component\String\s;
final class FunctionsTest extends TestCase
{
diff --git a/src/Symfony/Component/String/composer.json b/src/Symfony/Component/String/composer.json
index ec936e019d727..eb498b0847935 100644
--- a/src/Symfony/Component/String/composer.json
+++ b/src/Symfony/Component/String/composer.json
@@ -17,6 +17,7 @@
],
"require": {
"php": "^7.2.5",
+ "symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php
index 81a438fa577ef..af56b86b939c4 100644
--- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php
+++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\Translation\Tests;
use PHPUnit\Framework\TestCase;
+use Symfony\Component\Translation\Exception\RuntimeException;
use Symfony\Component\Translation\Loader\ArrayLoader;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Translator;
@@ -513,6 +514,16 @@ public function testIntlFormattedDomain()
$translator->addResource('array', ['some_message' => 'Hi {name}'], 'en', 'messages+intl-icu');
$this->assertSame('Hi Bob', $translator->trans('some_message', ['%name%' => 'Bob']));
}
+
+ public function testMissingLoaderForResourceError()
+ {
+ $this->expectException(RuntimeException::class);
+ $this->expectExceptionMessage('No loader is registered for the "twig" format when loading the "messages.en.twig" resource.');
+
+ $translator = new Translator('en');
+ $translator->addResource('twig', 'messages.en.twig', 'en');
+ $translator->getCatalogue('en');
+ }
}
class StringClass
diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php
index cefd5026bb674..81a71d1e66938 100644
--- a/src/Symfony/Component/Translation/Translator.php
+++ b/src/Symfony/Component/Translation/Translator.php
@@ -365,7 +365,11 @@ protected function doLoadCatalogue(string $locale): void
if (isset($this->resources[$locale])) {
foreach ($this->resources[$locale] as $resource) {
if (!isset($this->loaders[$resource[0]])) {
- throw new RuntimeException(sprintf('The "%s" translation loader is not registered.', $resource[0]));
+ if (\is_string($resource[1])) {
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format when loading the "%s" resource.', $resource[0], $resource[1]));
+ }
+
+ throw new RuntimeException(sprintf('No loader is registered for the "%s" format.', $resource[0]));
}
$this->catalogues[$locale]->addCatalogue($this->loaders[$resource[0]]->load($resource[1], $locale, $resource[2]));
}
diff --git a/src/Symfony/Component/VarDumper/Caster/RdKafkaCaster.php b/src/Symfony/Component/VarDumper/Caster/RdKafkaCaster.php
index bd3894ec11b0c..c3e4eb9f341c6 100644
--- a/src/Symfony/Component/VarDumper/Caster/RdKafkaCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/RdKafkaCaster.php
@@ -11,7 +11,6 @@
namespace Symfony\Component\VarDumper\Caster;
-use RdKafka;
use RdKafka\Conf;
use RdKafka\Exception as RdKafkaException;
use RdKafka\KafkaConsumer;
diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
index e6c5b17c43943..13b7fe33ecc9c 100644
--- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php
+++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php
@@ -91,6 +91,8 @@ public static function castFileInfo(\SplFileInfo $c, array $a, Stub $stub, bool
];
$prefix = Caster::PREFIX_VIRTUAL;
+ unset($a["\0SplFileInfo\0fileName"]);
+ unset($a["\0SplFileInfo\0pathName"]);
if (false === $c->getPathname()) {
$a[$prefix.'⚠'] = 'The parent constructor was not called: the object is in an invalid state';
@@ -173,6 +175,7 @@ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $s
{
$storage = [];
unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967
+ unset($a["\0SplObjectStorage\0storage"]);
$clone = clone $c;
foreach ($clone as $obj) {
diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
index d89fecf8bc970..c234b48e07afa 100644
--- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php
@@ -600,7 +600,7 @@ function showCurrent(state)
*/
return;
}
-
+
e.preventDefault();
search.className = search.className.replace(/\bsf-dump-search-hidden\b/, '');
searchInput.focus();
diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php
index 58b268dbc80a4..6b449b367c3e4 100644
--- a/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php
+++ b/src/Symfony/Component/VarDumper/Tests/Caster/RdKafkaCasterTest.php
@@ -20,6 +20,7 @@
/**
* @requires extension rdkafka
+ * @group integration
*/
class RdKafkaCasterTest extends TestCase
{
diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-iterator.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-iterator.php
index ed4df00c99e59..012bfb47a6a1e 100644
--- a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-iterator.php
+++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-iterator.php
@@ -14,6 +14,7 @@
123,
],
[],
+ null,
],
]
);
diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object-custom.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object-custom.php
index 530f0d1026ecd..98bef5101fcd9 100644
--- a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object-custom.php
+++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object-custom.php
@@ -16,6 +16,7 @@
[
"\0".'Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'."\0".'unused' => 123,
],
+ null,
],
]
);
diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object.php
index e2f349e6478f2..4e2d4d13a3d89 100644
--- a/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object.php
+++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/array-object.php
@@ -18,11 +18,13 @@
[
'foo' => $o[1],
],
+ null,
],
-1 => [
0,
[],
[],
+ null,
],
]
);
diff --git a/src/Symfony/Component/VarExporter/Tests/Fixtures/final-array-iterator.php b/src/Symfony/Component/VarExporter/Tests/Fixtures/final-array-iterator.php
index 7e838d1e789c0..afba945a1f05d 100644
--- a/src/Symfony/Component/VarExporter/Tests/Fixtures/final-array-iterator.php
+++ b/src/Symfony/Component/VarExporter/Tests/Fixtures/final-array-iterator.php
@@ -12,6 +12,7 @@
0,
[],
[],
+ null,
],
]
);
diff --git a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php
index c3482abedc7e9..55dfc12763665 100644
--- a/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php
+++ b/src/Symfony/Component/VarExporter/Tests/VarExporterTest.php
@@ -87,10 +87,12 @@ public function testExport(string $testName, $value, bool $staticValueExpected =
$dump = "= 70406 || !\in_array($testName, ['array-object', 'array-iterator', 'array-object-custom', 'spl-object-storage', 'final-array-iterator', 'final-error'], true)) {
+ $fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
+ } elseif (\PHP_VERSION_ID < 70400) {
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'-legacy.php';
} else {
- $fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
+ $this->markAsSkipped('PHP >= 7.4.6 required.');
}
$this->assertStringEqualsFile($fixtureFile, $dump);
diff --git a/src/Symfony/Component/VarExporter/composer.json b/src/Symfony/Component/VarExporter/composer.json
index 1678e352db7ea..6b19558a17af9 100644
--- a/src/Symfony/Component/VarExporter/composer.json
+++ b/src/Symfony/Component/VarExporter/composer.json
@@ -20,7 +20,7 @@
"symfony/polyfill-php80": "^1.15"
},
"require-dev": {
- "symfony/var-dumper": "^4.4|^5.0"
+ "symfony/var-dumper": "^4.4.9|^5.0.9"
},
"autoload": {
"psr-4": { "Symfony\\Component\\VarExporter\\": "" },
diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php
index 42dc3b1dc4527..1234ff43eebf8 100644
--- a/src/Symfony/Component/Yaml/Parser.php
+++ b/src/Symfony/Component/Yaml/Parser.php
@@ -764,7 +764,8 @@ private function parseValue(string $value, int $flags, string $context)
$lines[] = trim($this->currentLine);
// quoted string values end with a line that is terminated with the quotation character
- if ('' !== $this->currentLine && $this->currentLine[-1] === $quotation) {
+ $escapedLine = str_replace(['\\\\', '\\"'], '', $this->currentLine);
+ if ('' !== $escapedLine && $escapedLine[-1] === $quotation) {
break;
}
}
diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php
index debdc6b2cf55a..2a34d40cf72e7 100644
--- a/src/Symfony/Component/Yaml/Tests/ParserTest.php
+++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php
@@ -1529,6 +1529,33 @@ public function testBlankLinesInQuotedMultiLineString()
$this->assertSame($expected, $this->parser->parse($yaml));
}
+ public function testEscapedQuoteInQuotedMultiLineString()
+ {
+ $yaml = << 'foo "bar" baz',
+ ];
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
+ public function testBackslashInQuotedMultiLineString()
+ {
+ $yaml = << 'foo bar\\',
+ ];
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
public function testParseMultiLineUnquotedString()
{
$yaml = <<
- *
- * @experimental in 1.1
*/
interface ClientExceptionInterface extends HttpExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/DecodingExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/DecodingExceptionInterface.php
index 709db2189eb4b..971a7a29b3d67 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/DecodingExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/DecodingExceptionInterface.php
@@ -15,8 +15,6 @@
* When a content-type cannot be decoded to the expected representation.
*
* @author Nicolas Grekas
- *
- * @experimental in 1.1
*/
interface DecodingExceptionInterface extends ExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/ExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/ExceptionInterface.php
index 6d59715f70657..e553b47a1d64d 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/ExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/ExceptionInterface.php
@@ -15,8 +15,6 @@
* The base interface for all exceptions in the contract.
*
* @author Nicolas Grekas
- *
- * @experimental in 1.1
*/
interface ExceptionInterface extends \Throwable
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/HttpExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/HttpExceptionInterface.php
index 0e9f39f6ee827..17865ed367d24 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/HttpExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/HttpExceptionInterface.php
@@ -17,8 +17,6 @@
* Base interface for HTTP-related exceptions.
*
* @author Anton Chernikov
- *
- * @experimental in 1.1
*/
interface HttpExceptionInterface extends ExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/RedirectionExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/RedirectionExceptionInterface.php
index 8cdd3e70d76d0..edd9b8a9bb6e5 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/RedirectionExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/RedirectionExceptionInterface.php
@@ -15,8 +15,6 @@
* When a 3xx response is returned and the "max_redirects" option has been reached.
*
* @author Nicolas Grekas
- *
- * @experimental in 1.1
*/
interface RedirectionExceptionInterface extends HttpExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/ServerExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/ServerExceptionInterface.php
index f994ba2ddcbb6..9bfe1354b5246 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/ServerExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/ServerExceptionInterface.php
@@ -15,8 +15,6 @@
* When a 5xx response is returned.
*
* @author Nicolas Grekas
- *
- * @experimental in 1.1
*/
interface ServerExceptionInterface extends HttpExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Exception/TimeoutExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/TimeoutExceptionInterface.php
new file mode 100644
index 0000000000000..08acf9fb6db90
--- /dev/null
+++ b/src/Symfony/Contracts/HttpClient/Exception/TimeoutExceptionInterface.php
@@ -0,0 +1,21 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\HttpClient\Exception;
+
+/**
+ * When an idle timeout occurs.
+ *
+ * @author Nicolas Grekas
+ */
+interface TimeoutExceptionInterface extends TransportExceptionInterface
+{
+}
diff --git a/src/Symfony/Contracts/HttpClient/Exception/TransportExceptionInterface.php b/src/Symfony/Contracts/HttpClient/Exception/TransportExceptionInterface.php
index 1cdc30a2fc4f2..0c8d131a058e7 100644
--- a/src/Symfony/Contracts/HttpClient/Exception/TransportExceptionInterface.php
+++ b/src/Symfony/Contracts/HttpClient/Exception/TransportExceptionInterface.php
@@ -15,8 +15,6 @@
* When any error happens at the transport level.
*
* @author Nicolas Grekas
- *
- * @experimental in 1.1
*/
interface TransportExceptionInterface extends ExceptionInterface
{
diff --git a/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php b/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php
index 96486ca3168c8..d2990ac9efb0e 100644
--- a/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php
+++ b/src/Symfony/Contracts/HttpClient/Test/Fixtures/web/index.php
@@ -116,7 +116,7 @@
echo '<1>';
@ob_flush();
flush();
- usleep(500000);
+ usleep(600000);
echo '<2>';
exit;
diff --git a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php
index 8ef46a9a90eeb..ffbf4a42c73eb 100644
--- a/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php
+++ b/src/Symfony/Contracts/HttpClient/Test/HttpClientTestCase.php
@@ -14,13 +14,12 @@
use PHPUnit\Framework\TestCase;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
+use Symfony\Contracts\HttpClient\Exception\TimeoutExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
/**
* A reference test suite for HttpClientInterface implementations.
- *
- * @experimental in 1.1
*/
abstract class HttpClientTestCase extends TestCase
{
@@ -741,9 +740,35 @@ public function testTimeoutOnAccess()
$response->getHeaders();
}
- public function testTimeoutOnStream()
+ public function testTimeoutIsNotAFatalError()
{
usleep(300000); // wait for the previous test to release the server
+ $client = $this->getHttpClient(__FUNCTION__);
+ $response = $client->request('GET', 'http://localhost:8057/timeout-body', [
+ 'timeout' => 0.3,
+ ]);
+
+ try {
+ $response->getContent();
+ $this->fail(TimeoutExceptionInterface::class.' expected');
+ } catch (TimeoutExceptionInterface $e) {
+ }
+
+ for ($i = 0; $i < 10; ++$i) {
+ try {
+ $this->assertSame('<1><2>', $response->getContent());
+ break;
+ } catch (TimeoutExceptionInterface $e) {
+ }
+ }
+
+ if (10 === $i) {
+ throw $e;
+ }
+ }
+
+ public function testTimeoutOnStream()
+ {
$client = $this->getHttpClient(__FUNCTION__);
$response = $client->request('GET', 'http://localhost:8057/timeout-body');
diff --git a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php
index 0adb1a52a3036..16e9dad29939d 100644
--- a/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php
+++ b/src/Symfony/Contracts/HttpClient/Test/TestHttpServer.php
@@ -14,9 +14,6 @@
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
-/**
- * @experimental in 1.1
- */
class TestHttpServer
{
private static $started;
diff --git a/src/Symfony/Contracts/HttpClient/composer.json b/src/Symfony/Contracts/HttpClient/composer.json
index e91f2e52cd2de..31eac967e719f 100644
--- a/src/Symfony/Contracts/HttpClient/composer.json
+++ b/src/Symfony/Contracts/HttpClient/composer.json
@@ -27,7 +27,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "2.1-dev"
}
}
}
diff --git a/src/Symfony/Contracts/Service/composer.json b/src/Symfony/Contracts/Service/composer.json
index cbd491b59591f..08539a1cc318b 100644
--- a/src/Symfony/Contracts/Service/composer.json
+++ b/src/Symfony/Contracts/Service/composer.json
@@ -28,7 +28,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "2.1-dev"
}
}
}
diff --git a/src/Symfony/Contracts/Translation/composer.json b/src/Symfony/Contracts/Translation/composer.json
index d185b3a4394a2..cacc4b3d16b7c 100644
--- a/src/Symfony/Contracts/Translation/composer.json
+++ b/src/Symfony/Contracts/Translation/composer.json
@@ -27,7 +27,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "2.1-dev"
}
}
}