Skip to content

Commit f286fcc

Browse files
[DI] Replace wildcard-based methods autowiring by @required annotation
1 parent 9081699 commit f286fcc

22 files changed

+112
-259
lines changed

src/Symfony/Component/DependencyInjection/ChildDefinition.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,11 @@ public function setDeprecated($boolean = true, $template = null)
182182
/**
183183
* {@inheritdoc}
184184
*/
185-
public function setAutowiredCalls(array $autowiredCalls)
185+
public function setAutowired($autowired)
186186
{
187-
$this->changes['autowired_calls'] = true;
187+
$this->changes['autowired'] = true;
188188

189-
return parent::setAutowiredCalls($autowiredCalls);
189+
return parent::setAutowired($autowired);
190190
}
191191

192192
/**

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

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ public static function createResourceForClass(\ReflectionClass $reflectionClass)
9999
*/
100100
protected function processValue($value, $isRoot = false)
101101
{
102-
if (!$value instanceof Definition || !$value->getAutowiredCalls()) {
102+
if (!$value instanceof Definition || !$value->isAutowired()) {
103103
return parent::processValue($value, $isRoot);
104104
}
105105

106106
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass())) {
107107
return parent::processValue($value, $isRoot);
108108
}
109109

110-
$autowiredMethods = $this->getMethodsToAutowire($reflectionClass, $value->getAutowiredCalls());
110+
$autowiredMethods = $this->getMethodsToAutowire($reflectionClass);
111111
$methodCalls = $value->getMethodCalls();
112112

113113
if ($constructor = $reflectionClass->getConstructor()) {
@@ -142,48 +142,44 @@ protected function processValue($value, $isRoot = false)
142142
* Gets the list of methods to autowire.
143143
*
144144
* @param \ReflectionClass $reflectionClass
145-
* @param string[] $autowiredMethods
146145
*
147146
* @return \ReflectionMethod[]
148147
*/
149-
private function getMethodsToAutowire(\ReflectionClass $reflectionClass, array $autowiredMethods)
148+
private function getMethodsToAutowire(\ReflectionClass $reflectionClass)
150149
{
151150
$found = array();
152-
$regexList = array();
153151
$methodsToAutowire = array();
154152

155153
if ($reflectionMethod = $reflectionClass->getConstructor()) {
156-
$methodsToAutowire[$lcMethod = strtolower($reflectionMethod->name)] = $reflectionMethod;
157-
unset($autowiredMethods['__construct']);
158-
}
159-
if (!$autowiredMethods) {
160-
return $methodsToAutowire;
161-
}
162-
163-
foreach ($autowiredMethods as $pattern) {
164-
$regexList[] = '/^'.str_replace('\*', '.*', preg_quote($pattern, '/')).'$/i';
154+
$methodsToAutowire[strtolower($reflectionMethod->name)] = $reflectionMethod;
165155
}
166156

167157
foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $reflectionMethod) {
168158
if ($reflectionMethod->isStatic()) {
169159
continue;
170160
}
171-
172-
foreach ($regexList as $k => $regex) {
173-
if (preg_match($regex, $reflectionMethod->name)) {
174-
$found[] = $autowiredMethods[$k];
175-
$methodsToAutowire[strtolower($reflectionMethod->name)] = $reflectionMethod;
176-
continue 2;
177-
}
178-
}
179-
180161
if ($reflectionMethod->isAbstract() && !$reflectionMethod->getNumberOfParameters()) {
181162
$methodsToAutowire[strtolower($reflectionMethod->name)] = $reflectionMethod;
163+
continue;
182164
}
183-
}
165+
$r = $reflectionMethod;
184166

185-
if ($notFound = array_diff($autowiredMethods, $found)) {
186-
$this->container->log($this, sprintf('Autowiring\'s patterns "%s" for service "%s" don\'t match any method.', implode('", "', $notFound), $this->currentId));
167+
while (true) {
168+
if (false !== $doc = $r->getDocComment()) {
169+
if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
170+
$methodsToAutowire[strtolower($reflectionMethod->name)] = $reflectionMethod;
171+
break;
172+
}
173+
if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) {
174+
break;
175+
}
176+
}
177+
try {
178+
$r = $r->getPrototype();
179+
} catch (\ReflectionException $e) {
180+
break; // method has no prototype
181+
}
182+
}
187183
}
188184

189185
return $methodsToAutowire;
@@ -248,6 +244,9 @@ private function autowireMethod(\ReflectionMethod $reflectionMethod, array $argu
248244
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
249245
continue;
250246
}
247+
if (self::MODE_OPTIONAL === $mode && $parameter->isOptional() && !array_key_exists($index, $arguments)) {
248+
break;
249+
}
251250
if (method_exists($parameter, 'isVariadic') && $parameter->isVariadic()) {
252251
continue;
253252
}

src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionInheritancePass.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,9 @@ private function mergeDefinition(Definition $def, ChildDefinition $definition)
8282
if (isset($changes['abstract'])) {
8383
$def->setAbstract($definition->isAbstract());
8484
}
85-
if (isset($changes['autowired_calls'])) {
86-
$autowiredCalls = $def->getAutowiredCalls();
87-
}
8885

8986
ResolveDefinitionTemplatesPass::mergeDefinition($def, $definition);
9087

91-
// merge autowired calls
92-
if (isset($changes['autowired_calls'])) {
93-
$def->setAutowiredCalls(array_merge($autowiredCalls, $def->getAutowiredCalls()));
94-
}
95-
9688
// prepend instanceof tags
9789
$tailTags = $def->getTags();
9890
if ($headTags = $definition->getTags()) {

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

Lines changed: 3 additions & 3 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->setAutowiredCalls($parentDef->getAutowiredCalls());
104+
$def->setAutowired($parentDef->isAutowired());
105105

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

@@ -146,8 +146,8 @@ public static function mergeDefinition(Definition $def, ChildDefinition $definit
146146
if (isset($changes['deprecated'])) {
147147
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
148148
}
149-
if (isset($changes['autowired_calls'])) {
150-
$def->setAutowiredCalls($definition->getAutowiredCalls());
149+
if (isset($changes['autowired'])) {
150+
$def->setAutowired($definition->isAutowired());
151151
}
152152
if (isset($changes['decorated_service'])) {
153153
$decoratedService = $definition->getDecoratedService();

src/Symfony/Component/DependencyInjection/Definition.php

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Definition
3838
private $abstract = false;
3939
private $lazy = false;
4040
private $decoratedService;
41-
private $autowiredCalls = array();
41+
private $autowired = false;
4242
private $autowiringTypes = array();
4343

4444
protected $arguments;
@@ -737,48 +737,19 @@ public function setAutowiringTypes(array $types)
737737
*/
738738
public function isAutowired()
739739
{
740-
return !empty($this->autowiredCalls);
741-
}
742-
743-
/**
744-
* Gets autowired methods.
745-
*
746-
* @return string[]
747-
*/
748-
public function getAutowiredCalls()
749-
{
750-
return $this->autowiredCalls;
740+
return $this->autowired;
751741
}
752742

753743
/**
754744
* Sets autowired.
755745
*
756-
* Allowed values:
757-
* - true: constructor autowiring, same as $this->setAutowiredCalls(array('__construct'))
758-
* - false: no autowiring, same as $this->setAutowiredCalls(array())
759-
*
760746
* @param bool $autowired
761747
*
762748
* @return $this
763749
*/
764750
public function setAutowired($autowired)
765751
{
766-
return $this->setAutowiredCalls($autowired ? array('__construct') : array());
767-
}
768-
769-
/**
770-
* Sets autowired methods.
771-
*
772-
* Example of allowed value:
773-
* - array('__construct', 'set*', 'initialize'): autowire whitelisted methods only
774-
*
775-
* @param string[] $autowiredCalls
776-
*
777-
* @return $this
778-
*/
779-
public function setAutowiredCalls(array $autowiredCalls)
780-
{
781-
$this->autowiredCalls = $autowiredCalls;
752+
$this->autowired = (bool) $autowired;
782753

783754
return $this;
784755
}

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

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -165,33 +165,22 @@ private function getServiceDefaults(\DOMDocument $xml, $file)
165165
}
166166
$defaults = array(
167167
'tags' => $this->getChildren($defaultsNode, 'tag'),
168-
'autowire' => $this->getChildren($defaultsNode, 'autowire'),
169168
);
170169

171170
foreach ($defaults['tags'] as $tag) {
172171
if ('' === $tag->getAttribute('name')) {
173172
throw new InvalidArgumentException(sprintf('The tag name for tag "<defaults>" in %s must be a non-empty string.', $file));
174173
}
175174
}
175+
if ($defaultsNode->hasAttribute('autowire')) {
176+
$defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire'));
177+
}
176178
if ($defaultsNode->hasAttribute('public')) {
177179
$defaults['public'] = XmlUtils::phpize($defaultsNode->getAttribute('public'));
178180
}
179181
if ($defaultsNode->hasAttribute('inherit-tags')) {
180182
$defaults['inherit-tags'] = XmlUtils::phpize($defaultsNode->getAttribute('inherit-tags'));
181183
}
182-
if (!$defaultsNode->hasAttribute('autowire')) {
183-
foreach ($defaults['autowire'] as $k => $v) {
184-
$defaults['autowire'][$k] = $v->textContent;
185-
}
186-
187-
return $defaults;
188-
}
189-
if ($defaults['autowire']) {
190-
throw new InvalidArgumentException(sprintf('The "autowire" attribute cannot be used together with "<autowire>" tags for tag "<defaults>" in %s.', $file));
191-
}
192-
if (XmlUtils::phpize($defaultsNode->getAttribute('autowire'))) {
193-
$defaults['autowire'][] = '__construct';
194-
}
195184

196185
return $defaults;
197186
}
@@ -251,6 +240,8 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
251240

252241
if ($value = $service->getAttribute('autowire')) {
253242
$definition->setAutowired(XmlUtils::phpize($value));
243+
} elseif (isset($defaults['autowire'])) {
244+
$definition->setAutowired($defaults['autowire']);
254245
}
255246

256247
if ($files = $this->getChildren($service, 'file')) {
@@ -344,21 +335,6 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults =
344335
$definition->addAutowiringType($type->textContent);
345336
}
346337

347-
$autowiredCalls = array();
348-
foreach ($this->getChildren($service, 'autowire') as $tag) {
349-
$autowiredCalls[] = $tag->textContent;
350-
}
351-
352-
if ($autowiredCalls && $service->hasAttribute('autowire')) {
353-
throw new InvalidArgumentException(sprintf('The "autowire" attribute cannot be used together with "<autowire>" tags for service "%s" in %s.', $service->getAttribute('id'), $file));
354-
}
355-
356-
if ($autowiredCalls) {
357-
$definition->setAutowiredCalls($autowiredCalls);
358-
} elseif (!$service->hasAttribute('autowire') && !empty($defaults['autowire'])) {
359-
$definition->setAutowiredCalls($defaults['autowire']);
360-
}
361-
362338
if ($value = $service->getAttribute('decorates')) {
363339
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
364340
$priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;

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

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -498,21 +498,7 @@ private function parseDefinition($id, $service, $file, array $defaults)
498498
}
499499

500500
$autowire = isset($service['autowire']) ? $service['autowire'] : (isset($defaults['autowire']) ? $defaults['autowire'] : null);
501-
if (is_array($autowire)) {
502-
$autowiredCalls = array();
503-
504-
foreach ($autowire as $v) {
505-
if (is_string($v)) {
506-
$autowiredCalls[] = $v;
507-
} else {
508-
throw new InvalidArgumentException(sprintf('Parameter "autowire" must be boolean or string[] for service "%s" in %s. Check your YAML syntax.', $id, $file));
509-
}
510-
}
511-
512-
if ($autowiredCalls) {
513-
$definition->setAutowiredCalls($autowiredCalls);
514-
}
515-
} elseif (null !== $autowire) {
501+
if (null !== $autowire) {
516502
$definition->setAutowired($autowire);
517503
}
518504

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@
101101
</xsd:annotation>
102102
<xsd:choice maxOccurs="unbounded">
103103
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
104-
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
105104
</xsd:choice>
106105
<xsd:attribute name="public" type="boolean" />
107106
<xsd:attribute name="autowire" type="boolean" />
@@ -120,7 +119,6 @@
120119
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
121120
<xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
122121
<xsd:element name="autowiring-type" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
123-
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
124122
</xsd:choice>
125123
<xsd:attribute name="id" type="xsd:string" />
126124
<xsd:attribute name="class" type="xsd:string" />
@@ -148,7 +146,6 @@
148146
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
149147
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
150148
<xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
151-
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
152149
</xsd:choice>
153150
<xsd:attribute name="id" type="xsd:string" use="required" />
154151
<xsd:attribute name="shared" type="boolean" />
@@ -168,7 +165,6 @@
168165
<xsd:element name="tag" type="tag" minOccurs="0" maxOccurs="unbounded" />
169166
<xsd:element name="property" type="property" minOccurs="0" maxOccurs="unbounded" />
170167
<xsd:element name="getter" type="getter" minOccurs="0" maxOccurs="unbounded" />
171-
<xsd:element name="autowire" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
172168
</xsd:choice>
173169
<xsd:attribute name="namespace" type="xsd:string" use="required" />
174170
<xsd:attribute name="resource" type="xsd:string" use="required" />

src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ public function testSetLazy()
7171
$this->assertSame(array('lazy' => true), $def->getChanges());
7272
}
7373

74-
public function testSetAutowiredCalls()
74+
public function testSetAutowired()
7575
{
7676
$def = new ChildDefinition('foo');
7777

7878
$this->assertFalse($def->isAutowired());
79-
$this->assertSame($def, $def->setAutowiredCalls(array('foo', 'bar')));
80-
$this->assertEquals(array('foo', 'bar'), $def->getAutowiredCalls());
81-
$this->assertSame(array('autowired_calls' => true), $def->getChanges());
79+
$this->assertSame($def, $def->setAutowired(true));
80+
$this->assertTrue($def->isAutowired());
81+
$this->assertSame(array('autowired' => true), $def->getChanges());
8282
}
8383

8484
public function testSetArgument()

0 commit comments

Comments
 (0)