Skip to content

Commit 76865e5

Browse files
Make it really work on real apps
1 parent b366034 commit 76865e5

File tree

2 files changed

+58
-35
lines changed

2 files changed

+58
-35
lines changed

Compiler/AbstractRecursivePass.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,12 @@ protected function getConstructor(Definition $definition, $required)
133133
list($class, $method) = $factory;
134134
if ($class instanceof Reference) {
135135
$class = $this->container->findDefinition((string) $class)->getClass();
136+
} elseif ($class instanceof Definition) {
137+
$class = $class->getClass();
136138
} elseif (null === $class) {
137139
$class = $definition->getClass();
138140
}
141+
139142
if ('__construct' === $method) {
140143
throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
141144
}

Compiler/CheckTypeDeclarationsPass.php

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
15+
use Symfony\Component\DependencyInjection\Container;
1516
use Symfony\Component\DependencyInjection\Definition;
1617
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1718
use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException;
@@ -79,27 +80,27 @@ protected function processValue($value, $isRoot = false)
7980
/**
8081
* @throws InvalidArgumentException When not enough parameters are defined for the method
8182
*/
82-
private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $configurationArguments): void
83+
private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void
8384
{
8485
$numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters();
8586

86-
if (\count($configurationArguments) < $numberOfRequiredParameters) {
87-
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($configurationArguments)));
87+
if (\count($values) < $numberOfRequiredParameters) {
88+
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values)));
8889
}
8990

9091
$reflectionParameters = $reflectionFunction->getParameters();
91-
$checksCount = min($reflectionFunction->getNumberOfParameters(), \count($configurationArguments));
92+
$checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values));
9293

9394
for ($i = 0; $i < $checksCount; ++$i) {
9495
if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) {
9596
continue;
9697
}
9798

98-
$this->checkType($checkedDefinition, $configurationArguments[$i], $reflectionParameters[$i]);
99+
$this->checkType($checkedDefinition, $values[$i], $reflectionParameters[$i]);
99100
}
100101

101102
if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) {
102-
$variadicParameters = \array_slice($configurationArguments, $lastParameter->getPosition());
103+
$variadicParameters = \array_slice($values, $lastParameter->getPosition());
103104

104105
foreach ($variadicParameters as $variadicParameter) {
105106
$this->checkType($checkedDefinition, $variadicParameter, $lastParameter);
@@ -110,63 +111,82 @@ private function checkTypeDeclarations(Definition $checkedDefinition, \Reflectio
110111
/**
111112
* @throws InvalidParameterTypeException When a parameter is not compatible with the declared type
112113
*/
113-
private function checkType(Definition $checkedDefinition, $configurationArgument, \ReflectionParameter $parameter): void
114+
private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter): void
114115
{
115-
$parameterTypeName = $parameter->getType()->getName();
116+
$type = $parameter->getType()->getName();
116117

117-
$referencedDefinition = $configurationArgument;
118+
if ($value instanceof Reference) {
119+
if (!$this->container->has($value = (string) $value)) {
120+
return;
121+
}
118122

119-
if ($referencedDefinition instanceof Reference) {
120-
if (!$this->container->has($referencedDefinition)) {
123+
if ('service_container' === $value && is_a($type, Container::class, true)) {
121124
return;
122125
}
123126

124-
$referencedDefinition = $this->container->findDefinition((string) $referencedDefinition);
127+
$value = $this->container->findDefinition($value);
125128
}
126129

127-
if ('self' === $parameterTypeName) {
128-
$parameterTypeName = $parameter->getDeclaringClass()->getName();
130+
if ('self' === $type) {
131+
$type = $parameter->getDeclaringClass()->getName();
129132
}
130-
if ('static' === $parameterTypeName) {
131-
$parameterTypeName = $checkedDefinition->getClass();
133+
134+
if ('static' === $type) {
135+
$type = $checkedDefinition->getClass();
132136
}
133137

134-
if ($referencedDefinition instanceof Definition) {
135-
$class = $referencedDefinition->getClass();
138+
if ($value instanceof Definition) {
139+
$class = $value->getClass();
136140

137141
if (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) {
138142
return;
139143
}
140144

141-
if (!is_a($class, $parameterTypeName, true)) {
142-
throw new InvalidParameterTypeException($this->currentId, $class, $parameter);
143-
}
144-
} else {
145-
if (null === $configurationArgument && $parameter->allowsNull()) {
145+
if ('callable' === $type && method_exists($class, '__invoke')) {
146146
return;
147147
}
148148

149-
if (\in_array($parameterTypeName, self::SCALAR_TYPES, true) && is_scalar($configurationArgument)) {
149+
if ('iterable' === $type && is_subclass_of($class, 'Traversable')) {
150150
return;
151151
}
152152

153-
if ('iterable' === $parameterTypeName && $configurationArgument instanceof IteratorArgument) {
153+
if (is_a($class, $type, true)) {
154154
return;
155155
}
156156

157-
if ('Traversable' === $parameterTypeName && $configurationArgument instanceof IteratorArgument) {
158-
return;
159-
}
157+
throw new InvalidParameterTypeException($this->currentId, $class, $parameter);
158+
}
160159

161-
if ($configurationArgument instanceof Parameter) {
162-
return;
163-
}
160+
if ($value instanceof Parameter) {
161+
$value = $this->container->getParameter($value);
162+
} elseif (\is_string($value) && '%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) {
163+
$value = $this->container->getParameter($match[1]);
164+
}
164165

165-
$checkFunction = sprintf('is_%s', $parameter->getType()->getName());
166+
if (null === $value && $parameter->allowsNull()) {
167+
return;
168+
}
166169

167-
if (!$parameter->getType()->isBuiltin() || !$checkFunction($configurationArgument)) {
168-
throw new InvalidParameterTypeException($this->currentId, \gettype($configurationArgument), $parameter);
169-
}
170+
if (\in_array($type, self::SCALAR_TYPES, true) && is_scalar($value)) {
171+
return;
172+
}
173+
174+
if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition)) {
175+
return;
176+
}
177+
178+
if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) {
179+
return;
180+
}
181+
182+
if ('Traversable' === $type && ($value instanceof \Traversable || $value instanceof IteratorArgument)) {
183+
return;
184+
}
185+
186+
$checkFunction = sprintf('is_%s', $parameter->getType()->getName());
187+
188+
if (!$parameter->getType()->isBuiltin() || !$checkFunction($value)) {
189+
throw new InvalidParameterTypeException($this->currentId, \gettype($value), $parameter);
170190
}
171191
}
172192
}

0 commit comments

Comments
 (0)