Merge branch '3.4' into 4.1

* 3.4:
  [Twig] Replace for-loops with blocks for attributes
  [DI] fix reporting bindings on overriden services as unused
This commit is contained in:
Nicolas Grekas 2018-12-24 10:43:03 +01:00
commit ed1500fb4b
11 changed files with 77 additions and 25 deletions

View File

@ -98,7 +98,7 @@
{% set label = name|humanize %}
{%- endif -%}
{%- endif -%}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
{{- widget|raw }} {{ label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}}
</label>
{%- endif -%}

View File

@ -260,7 +260,7 @@
{%- endif -%}
{{ widget|raw }}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
{{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}}
{{- form_errors(form) -}}
</label>

View File

@ -350,7 +350,7 @@
{%- else -%}
{% set form_method = "POST" %}
{%- endif -%}
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{% for attrname, attrvalue in attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}{% if multipart %} enctype="multipart/form-data"{% endif %}>
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}>
{%- if form_method != method -%}
<input type="hidden" name="_method" value="{{ method }}" />
{%- endif -%}

View File

@ -258,7 +258,7 @@
{% set label = name|humanize %}
{%- endif -%}
{% endif %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
{{ widget|raw }}
{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}
</label>

View File

@ -34,6 +34,8 @@ class ResolveBindingsPass extends AbstractRecursivePass
*/
public function process(ContainerBuilder $container)
{
$this->usedBindings = $container->getRemovedBindingIds();
try {
parent::process($container);

View File

@ -122,6 +122,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private $removedIds = array();
private $removedBindingIds = array();
private static $internalTypes = array(
'int' => true,
'float' => true,
@ -498,7 +500,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id));
}
unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]);
$this->removeId($id);
unset($this->removedIds[$id]);
parent::set($id, $service);
}
@ -511,8 +514,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
public function removeDefinition($id)
{
if (isset($this->definitions[$id = (string) $id])) {
unset($this->definitions[$id]);
$this->removedIds[$id] = true;
$this->removeId($id);
}
}
@ -834,7 +836,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias));
}
unset($this->definitions[$alias], $this->removedIds[$alias]);
$this->removeId($alias);
unset($this->removedIds[$alias]);
return $this->aliasDefinitions[$alias] = $id;
}
@ -847,8 +850,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
public function removeAlias($alias)
{
if (isset($this->aliasDefinitions[$alias = (string) $alias])) {
unset($this->aliasDefinitions[$alias]);
$this->removedIds[$alias] = true;
$this->removeId($alias);
}
}
@ -977,7 +979,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
$id = (string) $id;
unset($this->aliasDefinitions[$id], $this->removedIds[$id]);
$this->removeId($id);
unset($this->removedIds[$id]);
return $this->definitions[$id] = $definition;
}
@ -1479,6 +1482,18 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return $services;
}
/**
* Gets removed binding ids.
*
* @return array
*
* @internal
*/
public function getRemovedBindingIds()
{
return $this->removedBindingIds;
}
/**
* Computes a reasonably unique hash of a value.
*
@ -1583,4 +1598,21 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
return false;
}
private function removeId($id)
{
$this->removedIds[$id] = true;
unset($this->aliasDefinitions[$id]);
if (!isset($this->definitions[$id])) {
return;
}
foreach ($this->definitions[$id]->getBindings() as $binding) {
list(, $identifier) = $binding->getValues();
$this->removedBindingIds[$identifier] = true;
}
unset($this->definitions[$id]);
}
}

View File

@ -111,4 +111,22 @@ class ResolveBindingsPassTest extends TestCase
$this->assertEquals(array(array('setDefaultLocale', array('fr'))), $definition->getMethodCalls());
}
public function testOverriddenBindings()
{
$container = new ContainerBuilder();
$binding = new BoundArgument('bar');
$container->register('foo', 'stdClass')
->setBindings(array('$foo' => clone $binding));
$container->register('bar', 'stdClass')
->setBindings(array('$foo' => clone $binding));
$container->register('foo', 'stdClass');
(new ResolveBindingsPass())->process($container);
$this->assertInstanceOf('stdClass', $container->get('foo'));
}
}

View File

@ -399,7 +399,7 @@ class ResolveChildDefinitionsPassTest extends TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
* @expectedExceptionMessageRegExp /^Circular reference detected for service "c", path: "c -> b -> a -> c"./
* @expectedExceptionMessageRegExp /^Circular reference detected for service "a", path: "a -> c -> b -> a"./
*/
public function testProcessDetectsChildDefinitionIndirectCircularReference()
{

View File

@ -559,7 +559,7 @@ class ContainerBuilderTest extends TestCase
$config->setDefinition('baz', new Definition('BazClass'));
$config->setAlias('alias_for_foo', 'foo');
$container->merge($config);
$this->assertEquals(array('service_container', 'foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');
$this->assertEquals(array('foo', 'bar', 'service_container', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');
$aliases = $container->getAliases();
$this->assertArrayHasKey('alias_for_foo', $aliases);

View File

@ -4,6 +4,9 @@ services:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
foo:
class: App\FooService
public: true
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo
public: true
@ -16,6 +19,3 @@ services:
shared: false
configurator: c
foo:
class: App\FooService
public: true

View File

@ -4,15 +4,6 @@ services:
class: Symfony\Component\DependencyInjection\ContainerInterface
public: true
synthetic: true
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo
public: true
tags:
- { name: foo }
- { name: baz }
deprecated: '%service_id%'
arguments: [1]
factory: f
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar
public: true
@ -23,3 +14,12 @@ services:
lazy: true
arguments: [1]
factory: f
Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo:
class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo
public: true
tags:
- { name: foo }
- { name: baz }
deprecated: '%service_id%'
arguments: [1]
factory: f