Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 36d76e9

Browse filesBrowse files
[DI] Add side-effect-restricted variant for autowiring, based solely on ids
1 parent 6643fe2 commit 36d76e9
Copy full SHA for 36d76e9

File tree

17 files changed

+140
-54
lines changed
Filter options

17 files changed

+140
-54
lines changed

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ private function getContainerDefinitionData(Definition $definition, $omitTags =
221221
'lazy' => $definition->isLazy(),
222222
'shared' => $definition->isShared(),
223223
'abstract' => $definition->isAbstract(),
224-
'autowire' => $definition->isAutowired(),
224+
'autowire' => $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : false,
225225
);
226226

227227
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ protected function describeContainerDefinition(Definition $definition, array $op
182182
."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no')
183183
."\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no')
184184
."\n".'- Abstract: '.($definition->isAbstract() ? 'yes' : 'no')
185-
."\n".'- Autowired: '.($definition->isAutowired() ? 'yes' : 'no')
185+
."\n".'- Autowired: '.($definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'no')
186186
;
187187

188188
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ protected function describeContainerDefinition(Definition $definition, array $op
295295
$tableRows[] = array('Lazy', $definition->isLazy() ? 'yes' : 'no');
296296
$tableRows[] = array('Shared', $definition->isShared() ? 'yes' : 'no');
297297
$tableRows[] = array('Abstract', $definition->isAbstract() ? 'yes' : 'no');
298-
$tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no');
298+
$tableRows[] = array('Autowired', $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'no');
299299

300300
if ($autowiringTypes = $definition->getAutowiringTypes(false)) {
301301
$tableRows[] = array('Autowiring Types', implode(', ', $autowiringTypes));

‎src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
371371
$serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false');
372372
$serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
373373
$serviceXML->setAttribute('abstract', $definition->isAbstract() ? 'true' : 'false');
374-
$serviceXML->setAttribute('autowired', $definition->isAutowired() ? 'true' : 'false');
374+
$serviceXML->setAttribute('autowired', $definition->isAutowired() ? (Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id') : 'false');
375375
$serviceXML->setAttribute('file', $definition->getFile());
376376

377377
$calls = $definition->getMethodCalls();

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+57-21Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
use Symfony\Component\DependencyInjection\TypedReference;
2121

2222
/**
23-
* Guesses constructor arguments of services definitions and try to instantiate services if necessary.
23+
* Inspects existing service definitions and wires the autowired ones using the type hints of their classes.
2424
*
2525
* @author Kévin Dunglas <dunglas@gmail.com>
26+
* @author Nicolas Grekas <p@tchwork.com>
2627
*/
2728
class AutowirePass extends AbstractRecursivePass
2829
{
@@ -280,13 +281,7 @@ private function autowireMethod(\ReflectionMethod $reflectionMethod, array $argu
280281
} elseif ($parameter->allowsNull()) {
281282
$value = null;
282283
} else {
283-
if ($classOrInterface = class_exists($type, false) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
284-
$message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $type, $this->currentId, $classOrInterface);
285-
} else {
286-
$message = sprintf('Cannot autowire argument $%s of method %s::%s() for service "%s": Class %s does not exist.', $parameter->name, $reflectionMethod->class, $reflectionMethod->name, $this->currentId, $type);
287-
}
288-
289-
throw new RuntimeException($message);
284+
throw $this->createTypeNotFoundException($type, 'argument $'.$parameter->name.' of method '.$reflectionMethod->class.'::'.$reflectionMethod->name.'()');
290285
}
291286

292287
$arguments[$index] = $value;
@@ -339,17 +334,23 @@ private function getAutowiredReference($type, $autoRegister = true)
339334
return new Reference($type);
340335
}
341336

342-
if (null === $this->types) {
343-
$this->populateAvailableTypes();
344-
}
337+
if (Definition::AUTOWIRE_BY_TYPE === $this->currentDefinition->getAutowired()) {
338+
if (null === $this->types) {
339+
$this->populateAvailableTypes();
340+
}
341+
342+
if (isset($this->types[$type])) {
343+
$this->container->log($this, sprintf('Service "%s" matches type "%s" thus has been autowired into service "%s".', $this->types[$type], $type, $this->currentId));
345344

346-
if (isset($this->types[$type])) {
347-
return new Reference($this->types[$type]);
345+
return new Reference($this->types[$type]);
346+
}
348347
}
349348

350349
if ($autoRegister && $class = $this->container->getReflectionClass($type, true)) {
351350
return $this->createAutowiredDefinition($class);
352351
}
352+
353+
$this->container->log($this, sprintf('Type "%s" cannot be autowired for service "%s".', $type, $this->currentId));
353354
}
354355

355356
/**
@@ -449,22 +450,57 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint)
449450
}
450451

451452
if (!$typeHint->isInstantiable()) {
453+
$this->container->log($this, sprintf('Type "%s" is not instantiable thus cannot be auto-registered for service "%s".', $typeHint->name, $this->currentId));
454+
452455
return;
453456
}
454457

455458
$currentId = $this->currentId;
456-
$this->currentId = $argumentId = sprintf('autowired.%s', $typeHint->name);
459+
$this->currentId = $type = $typeHint->name;
457460

458-
$argumentDefinition = $this->container->register($argumentId, $typeHint->name);
459-
$argumentDefinition->setPublic(false);
460-
$argumentDefinition->setAutowired(true);
461+
$typeDefinition = (new Definition($typeHint->name))
462+
->setPublic(false)
463+
->setAutowired($this->currentDefinition->getAutowired())
464+
->addTag('container.autoregistered');
461465

462-
$this->populateAvailableType($argumentId, $argumentDefinition);
466+
if (null !== $this->types) {
467+
$this->populateAvailableType($type, $typeDefinition);
468+
}
469+
470+
try {
471+
$this->processValue($typeDefinition, true);
472+
$this->container->setDefinition($type, $typeDefinition);
473+
} catch (RuntimeException $e) {
474+
$this->container->log($this, sprintf('Type "%s" cannot be auto-registered for service "%s": %s.', $type, $this->currentId, $e->getMessage()));
463475

464-
$this->processValue($argumentDefinition, true);
465-
$this->currentId = $currentId;
476+
return;
477+
} finally {
478+
$this->currentId = $currentId;
479+
}
480+
$this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId));
481+
482+
return new Reference($type);
483+
}
484+
485+
private function createTypeNotFoundException($type, $label)
486+
{
487+
if (!$classOrInterface = class_exists($type, false) ? 'class' : (interface_exists($type, false) ? 'interface' : null)) {
488+
return new RuntimeException(sprintf('Cannot autowire %s for service "%s": Class or interface "%s" does not exist.', $label, $this->currentId, $type));
489+
}
490+
if (null === $this->types) {
491+
$this->populateAvailableTypes();
492+
}
493+
if (Definition::AUTOWIRE_BY_TYPE === $this->currentDefinition->getAutowired()) {
494+
$message = sprintf('No services were found matching the "%s" %s and it cannot be auto-registered', $type, $classOrInterface);
495+
} elseif (isset($this->ambiguousServiceTypes[$type])) {
496+
$message = sprintf('Service "%s" does not exist and it cannot be auto-registered. This type could be aliased to any of these existing services: "%s"', $type, implode('", "', $this->ambiguousServiceTypes[$type]));
497+
} elseif (isset($this->types[$type])) {
498+
$message = sprintf('Service "%s" does not exist and it cannot be auto-registered. This type could be aliased to the existing "%s" service', $type, $this->types[$type]);
499+
} else {
500+
$message = sprintf('Service "%s" does not exist and it cannot be auto-registered', $type);
501+
}
466502

467-
return new Reference($argumentId);
503+
return new RuntimeException(sprintf('Cannot autowire %s for service "%s": %s.', $label, $this->currentId, $message));
468504
}
469505

470506
/**

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private function doResolveDefinition(ChildDefinition $definition)
101101
$def->setFile($parentDef->getFile());
102102
$def->setPublic($parentDef->isPublic());
103103
$def->setLazy($parentDef->isLazy());
104-
$def->setAutowired($parentDef->isAutowired());
104+
$def->setAutowired($parentDef->getAutowired());
105105

106106
self::mergeDefinition($def, $definition);
107107

@@ -147,7 +147,7 @@ public static function mergeDefinition(Definition $def, ChildDefinition $definit
147147
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
148148
}
149149
if (isset($changes['autowired'])) {
150-
$def->setAutowired($definition->isAutowired());
150+
$def->setAutowired($definition->getAutowired());
151151
}
152152
if (isset($changes['decorated_service'])) {
153153
$decoratedService = $definition->getDecoratedService();

‎src/Symfony/Component/DependencyInjection/Definition.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Definition.php
+21-3Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
*/
2222
class Definition
2323
{
24+
const AUTOWIRE_BY_TYPE = 1;
25+
const AUTOWIRE_BY_ID = 2;
26+
2427
private $class;
2528
private $file;
2629
private $factory;
@@ -38,7 +41,7 @@ class Definition
3841
private $abstract = false;
3942
private $lazy = false;
4043
private $decoratedService;
41-
private $autowired = false;
44+
private $autowired = 0;
4245
private $autowiringTypes = array();
4346

4447
protected $arguments;
@@ -736,20 +739,35 @@ public function setAutowiringTypes(array $types)
736739
* @return bool
737740
*/
738741
public function isAutowired()
742+
{
743+
return (bool) $this->autowired;
744+
}
745+
746+
/**
747+
* Gets the autowiring mode.
748+
*
749+
* @return int
750+
*/
751+
public function getAutowired()
739752
{
740753
return $this->autowired;
741754
}
742755

743756
/**
744757
* Sets autowired.
745758
*
746-
* @param bool $autowired
759+
* @param bool|int $autowired
747760
*
748761
* @return $this
749762
*/
750763
public function setAutowired($autowired)
751764
{
752-
$this->autowired = (bool) $autowired;
765+
$autowired = (int) $autowired;
766+
767+
if ($autowired && self::AUTOWIRE_BY_TYPE !== $autowired && self::AUTOWIRE_BY_ID !== $autowired) {
768+
throw new InvalidArgumentException(sprintf('Invalid argument: Definition::AUTOWIRE_BY_TYPE (%d) or Definition::AUTOWIRE_BY_ID (%d) expected, %d given.', self::AUTOWIRE_BY_TYPE, self::AUTOWIRE_BY_ID, $autowired));
769+
}
770+
$this->autowired = $autowired;
753771

754772
return $this;
755773
}

‎src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,10 +734,11 @@ private function addService($id, Definition $definition)
734734
}
735735

736736
if ($definition->isAutowired()) {
737+
$autowired = Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'types' : 'ids';
737738
$doc .= <<<EOF
738739
739740
*
740-
* This service is autowired.
741+
* This service is autowired by {$autowired}.
741742
EOF;
742743
}
743744

‎src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ private function addService($definition, $id, \DOMElement $parent)
199199
}
200200

201201
if ($definition->isAutowired()) {
202-
$service->setAttribute('autowire', 'true');
202+
$service->setAttribute('autowire', Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by-type' : 'by-id');
203203
}
204204

205205
foreach ($definition->getAutowiringTypes(false) as $autowiringTypeValue) {

‎src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ private function addService($id, $definition)
106106
}
107107

108108
if ($definition->isAutowired()) {
109-
$code .= " autowire: true\n";
109+
$code .= sprintf(" autowire: %s\n", Definition::AUTOWIRE_BY_TYPE === $definition->getAutowired() ? 'by_type' : 'by_id');
110110
}
111111

112112
$autowiringTypesCode = '';

‎src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+19-2Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ private function getServiceDefaults(\DOMDocument $xml, $file)
172172
}
173173
}
174174
if ($defaultsNode->hasAttribute('autowire')) {
175-
$defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire'));
175+
$defaults['autowire'] = $this->getAutowired($defaultsNode->getAttribute('autowire'), $file);
176176
}
177177
if ($defaultsNode->hasAttribute('public')) {
178178
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
@@ -238,7 +238,7 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
238238
}
239239

240240
if ($value = $service->getAttribute('autowire')) {
241-
$definition->setAutowired(XmlUtils::phpize($value));
241+
$definition->setAutowired($this->getAutowired($value, $file));
242242
} elseif (isset($defaults['autowire'])) {
243243
$definition->setAutowired($defaults['autowire']);
244244
}
@@ -666,6 +666,23 @@ private function loadFromExtensions(\DOMDocument $xml)
666666
}
667667
}
668668

669+
private function getAutowired($value, $file)
670+
{
671+
if (is_bool($value = XmlUtils::phpize($value))) {
672+
return $value;
673+
}
674+
675+
if ('by-type' === $value) {
676+
return Definition::AUTOWIRE_BY_TYPE;
677+
}
678+
679+
if ('by-id' === $value) {
680+
return Definition::AUTOWIRE_BY_ID;
681+
}
682+
683+
throw new InvalidArgumentException(sprintf('Invalid autowire attribute: "by-type", "by-id", "true" or "false" expected, "%s" given in "%s".', $value, $file));
684+
}
685+
669686
/**
670687
* Converts a \DomElement object to a PHP array.
671688
*

‎src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,14 @@ private function parseDefinition($id, $service, $file, array $defaults)
500500

501501
$autowire = isset($service['autowire']) ? $service['autowire'] : (isset($defaults['autowire']) ? $defaults['autowire'] : null);
502502
if (null !== $autowire) {
503+
if ('by_type' === $autowire) {
504+
$autowire = Definition::AUTOWIRE_BY_TYPE;
505+
} elseif ('by_id' === $autowire) {
506+
$autowire = Definition::AUTOWIRE_BY_ID;
507+
} elseif (!is_bool($autowire)) {
508+
throw new InvalidArgumentException(sprintf('Invalid autowire attribute: "by_type", "by_id", true or false expected, "%s" given in "%s".', is_string($autowire) ? $autowire : gettype($autowire), $file));
509+
}
510+
503511
$definition->setAutowired($autowire);
504512
}
505513

‎src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
+10-4Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@
102102
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
103103
</xsd:choice>
104104
<xsd:attribute name="public" type="boolean" />
105-
<xsd:attribute name="autowire" type="boolean" />
105+
<xsd:attribute name="autowire" type="autowire" />
106106
<xsd:attribute name="inherit-tags" type="boolean" />
107107
</xsd:complexType>
108108

@@ -131,7 +131,7 @@
131131
<xsd:attribute name="decorates" type="xsd:string" />
132132
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
133133
<xsd:attribute name="decoration-priority" type="xsd:integer" />
134-
<xsd:attribute name="autowire" type="boolean" />
134+
<xsd:attribute name="autowire" type="autowire" />
135135
<xsd:attribute name="inherit-tags" type="boolean" />
136136
</xsd:complexType>
137137

@@ -151,7 +151,7 @@
151151
<xsd:attribute name="public" type="boolean" />
152152
<xsd:attribute name="lazy" type="boolean" />
153153
<xsd:attribute name="abstract" type="boolean" />
154-
<xsd:attribute name="autowire" type="boolean" />
154+
<xsd:attribute name="autowire" type="autowire" />
155155
</xsd:complexType>
156156

157157
<xsd:complexType name="prototype">
@@ -172,7 +172,7 @@
172172
<xsd:attribute name="lazy" type="boolean" />
173173
<xsd:attribute name="abstract" type="boolean" />
174174
<xsd:attribute name="parent" type="xsd:string" />
175-
<xsd:attribute name="autowire" type="boolean" />
175+
<xsd:attribute name="autowire" type="autowire" />
176176
<xsd:attribute name="inherit-tags" type="boolean" />
177177
</xsd:complexType>
178178

@@ -279,4 +279,10 @@
279279
<xsd:pattern value="(%.+%|true|false)" />
280280
</xsd:restriction>
281281
</xsd:simpleType>
282+
283+
<xsd:simpleType name="autowire">
284+
<xsd:restriction base="xsd:string">
285+
<xsd:pattern value="(true|false|by-type|by-id)" />
286+
</xsd:restriction>
287+
</xsd:simpleType>
282288
</xsd:schema>

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.