Merge branch '4.4' into 5.0

* 4.4:
  [DI] fix loading defaults when using the PHP-DSL
  RepeatedType should always have inner types mapped
This commit is contained in:
Nicolas Grekas 2020-04-13 12:13:27 +02:00
commit 8647ad3b2b
20 changed files with 99 additions and 27 deletions

View File

@ -355,7 +355,7 @@ class TextDescriptor extends Descriptor
protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $builder = null)
{
if ($alias->isPublic()) {
if ($alias->isPublic() && !$alias->isPrivate()) {
$options['output']->comment(sprintf('This service is a <info>public</info> alias for the service <info>%s</info>', (string) $alias));
} else {
$options['output']->comment(sprintf('This service is a <comment>private</comment> alias for the service <info>%s</info>', (string) $alias));

View File

@ -55,7 +55,9 @@ class CacheCollectorPass implements CompilerPassInterface
$recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class);
$recorder->setTags($definition->getTags());
$recorder->setPublic($definition->isPublic());
if (!$definition->isPublic() || !$definition->isPrivate()) {
$recorder->setPublic($definition->isPublic());
}
$recorder->setArguments([new Reference($innerId = $id.$this->cachePoolRecorderInnerSuffix)]);
$definition->setTags([]);

View File

@ -42,7 +42,7 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator
/**
* Registers a service.
*/
final public function set(string $id, string $class = null): ServiceConfigurator
final public function set(?string $id, string $class = null): ServiceConfigurator
{
$this->__destruct();

View File

@ -45,10 +45,13 @@ class PrototypeConfigurator extends AbstractServiceConfigurator
public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent)
{
$definition = new Definition();
$definition->setPublic($defaults->isPublic());
if (!$defaults->isPublic() || !$defaults->isPrivate()) {
$definition->setPublic($defaults->isPublic());
}
$definition->setAutowired($defaults->isAutowired());
$definition->setAutoconfigured($defaults->isAutoconfigured());
$definition->setBindings($defaults->getBindings());
// deep clone, to avoid multiple process of the same instance in the passes
$definition->setBindings(unserialize(serialize($defaults->getBindings())));
$definition->setChanges([]);
$this->loader = $loader;

View File

@ -83,13 +83,14 @@ class ServicesConfigurator extends AbstractConfigurator
$id = sprintf('.%d_%s', ++$this->anonymousCount, preg_replace('/^.*\\\\/', '', $class).'~'.$this->anonymousHash);
$definition->setPublic(false);
} else {
$definition->setPublic($defaults->isPublic());
} elseif (!$defaults->isPublic() || !$defaults->isPrivate()) {
$definition->setPublic($defaults->isPublic() && !$defaults->isPrivate());
}
$definition->setAutowired($defaults->isAutowired());
$definition->setAutoconfigured($defaults->isAutoconfigured());
$definition->setBindings($defaults->getBindings());
// deep clone, to avoid multiple process of the same instance in the passes
$definition->setBindings(unserialize(serialize($defaults->getBindings())));
$definition->setChanges([]);
$configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags(), $this->path);
@ -103,7 +104,10 @@ class ServicesConfigurator extends AbstractConfigurator
final public function alias(string $id, string $referencedId): AliasConfigurator
{
$ref = static::processValue($referencedId, true);
$alias = new Alias((string) $ref, $this->defaults->isPublic());
$alias = new Alias((string) $ref);
if (!$this->defaults->isPublic() || !$this->defaults->isPrivate()) {
$alias->setPublic($this->defaults->isPublic());
}
$this->container->setAlias($id, $alias);
return new AliasConfigurator($this, $alias);

View File

@ -7,7 +7,7 @@ use stdClass;
use Symfony\Component\DependencyInjection\Tests\Fixtures\StdClassDecorator;
return function (ContainerConfigurator $c) {
$s = $c->services();
$s = $c->services()->defaults()->public();
$s->set('decorated', stdClass::class);

View File

@ -5,7 +5,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
use App\BarService;
return function (ContainerConfigurator $c) {
$s = $c->services();
$s = $c->services()->defaults()->public();
$s->set(BarService::class)
->args([inline('FooClass')]);
};

View File

@ -6,12 +6,14 @@ use App\BarService;
return function (ContainerConfigurator $c) {
$c->services()
->set('bar', 'Class1')
->set('bar', 'Class1')->public()
->set(BarService::class)
->public()
->abstract(true)
->lazy()
->set('foo')
->parent(BarService::class)
->public()
->decorate('bar', 'b', 1)
->args([ref('b')])
->class('Class2')

View File

@ -18,7 +18,7 @@ services:
arguments: ['@bar']
bar:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo
public: false
public: true
tags:
- { name: t, a: b }
autowire: true

View File

@ -14,7 +14,7 @@ return function (ContainerConfigurator $c) {
->autowire()
->tag('t', ['a' => 'b'])
->bind(Foo::class, ref('bar'))
->private();
->public();
$s->set(Foo::class)->args([ref('bar')])->public();
$s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false);

View File

@ -6,7 +6,7 @@ use App\FooService;
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
return function (ContainerConfigurator $c) {
$s = $c->services();
$s = $c->services()->defaults()->public();
$s->instanceof(Prototype\Foo::class)
->property('p', 0)
->call('setFoo', [ref('foo')])

View File

@ -3,6 +3,6 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
return function (ContainerConfigurator $c) {
$di = $c->services();
$di = $c->services()->defaults()->public();
$di->set('foo', 'stdClass')->lazy('SomeInterface');
};

View File

@ -7,7 +7,7 @@ use App\BarService;
return new class() {
public function __invoke(ContainerConfigurator $c)
{
$s = $c->services();
$s = $c->services()->defaults()->public();
$s->set(BarService::class)
->args([inline('FooClass')]);
}

View File

@ -9,7 +9,7 @@ return function (ContainerConfigurator $c) {
('foo', 'Foo')
('bar', 'Bar')
;
$c->services()
$c->services()->defaults()->public()
(Foo::class)
->arg('$bar', ref('bar'))
->public()

View File

@ -8,6 +8,7 @@ return function (ContainerConfigurator $c) {
$di = $c->services()->defaults()
->tag('baz');
$di->load(Prototype::class.'\\', '../Prototype')
->public()
->autoconfigure()
->exclude('../Prototype/{OtherDir,BadClasses,SinglyImplementedInterface}')
->factory('f')
@ -17,6 +18,6 @@ return function (ContainerConfigurator $c) {
->autoconfigure(false)
->tag('foo')
->parent('foo');
$di->set('foo')->lazy()->abstract();
$di->set('foo')->lazy()->abstract()->public();
$di->get(Prototype\Foo::class)->lazy(false);
};

View File

@ -8,6 +8,7 @@ return function (ContainerConfigurator $c) {
$di = $c->services()->defaults()
->tag('baz');
$di->load(Prototype::class.'\\', '../Prototype')
->public()
->autoconfigure()
->exclude(['../Prototype/OtherDir', '../Prototype/BadClasses', '../Prototype/SinglyImplementedInterface'])
->factory('f')
@ -17,6 +18,6 @@ return function (ContainerConfigurator $c) {
->autoconfigure(false)
->tag('foo')
->parent('foo');
$di->set('foo')->lazy()->abstract();
$di->set('foo')->lazy()->abstract()->public();
$di->get(Prototype\Foo::class)->lazy(false);
};

View File

@ -16,8 +16,7 @@ return function (ContainerConfigurator $c) {
$p->set('foo_class', FooClass::class)
->set('foo', 'bar');
$s = $c->services()->defaults()
->public();
$s = $c->services()->defaults()->public();
$s->set('foo')
->args(['foo', ref('foo.baz'), ['%foo%' => 'foo is %foo%', 'foobar' => '%foo%'], true, ref('service_container')])
->class(FooClass::class)
@ -127,12 +126,10 @@ return function (ContainerConfigurator $c) {
->tag('foo');
$s->set('tagged_iterator', 'Bar')
->public()
->args([tagged_iterator('foo')]);
$s->set('runtime_error', 'stdClass')
->args([new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)])
->public();
->args([new Reference('errored_definition', ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE)]);
$s->set('errored_definition', 'stdClass')->private();
$s->alias('alias_for_foo', 'foo')->private()->public();

View File

@ -31,13 +31,16 @@ class RepeatedType extends AbstractType
$options['options']['error_bubbling'] = $options['error_bubbling'];
}
// children fields must always be mapped
$defaultOptions = ['mapped' => true];
$builder
->addViewTransformer(new ValueToDuplicatesTransformer([
$options['first_name'],
$options['second_name'],
]))
->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options']))
->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options']))
->add($options['first_name'], $options['type'], array_merge($options['options'], $options['first_options'], $defaultOptions))
->add($options['second_name'], $options['type'], array_merge($options['options'], $options['second_options'], $defaultOptions))
;
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\Tests\Fixtures\NotMappedType;
class RepeatedTypeTest extends BaseTypeTest
{
@ -78,6 +79,41 @@ class RepeatedTypeTest extends BaseTypeTest
$this->assertFalse($form['second']->isRequired());
}
public function testMappedOverridesDefault()
{
$form = $this->factory->create(NotMappedType::class);
$this->assertFalse($form->getConfig()->getMapped());
$form = $this->factory->create(static::TESTED_TYPE, null, [
'type' => NotMappedType::class,
]);
$this->assertTrue($form['first']->getConfig()->getMapped());
$this->assertTrue($form['second']->getConfig()->getMapped());
}
/**
* @dataProvider notMappedConfigurationKeys
*/
public function testNotMappedInnerIsOverridden($configurationKey)
{
$form = $this->factory->create(static::TESTED_TYPE, null, [
'type' => TextTypeTest::TESTED_TYPE,
$configurationKey => ['mapped' => false],
]);
$this->assertTrue($form['first']->getConfig()->getMapped());
$this->assertTrue($form['second']->getConfig()->getMapped());
}
public function notMappedConfigurationKeys()
{
return [
['first_options'],
['second_options'],
];
}
public function testSetInvalidOptions()
{
$this->expectException('Symfony\Component\OptionsResolver\Exception\InvalidOptionsException');

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Form\Tests\Fixtures;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class NotMappedType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('mapped', false);
}
}