Merge branch '5.0'
* 5.0: [DI] fix loading defaults when using the PHP-DSL RepeatedType should always have inner types mapped
This commit is contained in:
commit
e94506bee7
@ -386,7 +386,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));
|
||||
|
@ -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([]);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -81,13 +81,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, true, $this, $definition, $id, $defaults->getTags(), $this->path);
|
||||
@ -101,7 +102,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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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([service('FooClass')]);
|
||||
};
|
||||
|
@ -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')
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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')])
|
||||
|
@ -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');
|
||||
};
|
||||
|
@ -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([service('FooClass')]);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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->set('preload_sidekick', 'stdClass')
|
||||
->tag('container.preload', ['class' => 'Some\Sidekick1'])
|
||||
|
@ -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))
|
||||
;
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
|
23
src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php
Normal file
23
src/Symfony/Component/Form/Tests/Fixtures/NotMappedType.php
Normal 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);
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
|
||||
|
||||
$publicAliases = [];
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($alias->isPublic()) {
|
||||
if ($alias->isPublic() && !$alias->isPrivate()) {
|
||||
$publicAliases[(string) $alias][] = $id;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user