Skip to content

Commit 8174a0d

Browse files
Merge pull request #35 from Ezaki113/master
Fix bug "Validation fails with factory service "public" set to `false`"
2 parents cffffb0 + 58fdcba commit 8174a0d

File tree

4 files changed

+135
-1
lines changed

4 files changed

+135
-1
lines changed

ConstructorResolver.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public function resolve(Definition $definition)
3636
return $this->resolveFactoryServiceWithMethod((string) $factory[0], $factory[1]);
3737
}
3838

39+
if (is_array($factory) && $factory[0] instanceof Definition) {
40+
return $this->resolveFactoryServiceDefinitionWithMethod($factory[0], $factory[1]);
41+
}
42+
3943
if (is_array($factory)) {
4044
return $this->resolveFactoryClassWithMethod($factory[0], $factory[1]);
4145
}
@@ -133,4 +137,15 @@ private function resolveFactoryFunction($factory)
133137

134138
return new \ReflectionFunction($factory);
135139
}
140+
141+
private function resolveFactoryServiceDefinitionWithMethod(Definition $factoryDefinition, $factoryMethod)
142+
{
143+
$factoryClass = $this->resultingClassResolver->resolve($factoryDefinition);
144+
145+
if (!method_exists($factoryClass, $factoryMethod)) {
146+
throw new MethodNotFoundException($factoryClass, $factoryMethod);
147+
}
148+
149+
return new \ReflectionMethod($factoryClass, $factoryMethod);
150+
}
136151
}

ServiceDefinitionValidator.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use Matthias\SymfonyServiceDefinitionValidator\Exception\ServiceNotFoundException;
1010
use Symfony\Component\DependencyInjection\ContainerBuilder;
1111
use Symfony\Component\DependencyInjection\Definition;
12-
use Symfony\Component\DependencyInjection\Reference;
1312

1413
class ServiceDefinitionValidator implements ServiceDefinitionValidatorInterface
1514
{
@@ -95,6 +94,8 @@ private function validateFactory(Definition $definition)
9594
list($factoryClassOrService, $method) = $factory;
9695
if (is_string($factoryClassOrService)) {
9796
$this->validateFactoryClassAndMethod($factoryClassOrService, $method);
97+
} elseif ($factoryClassOrService instanceof Definition) {
98+
$this->validateFactoryServiceDefinitionAndMethod($factoryClassOrService, $method);
9899
} else {
99100
$this->validateFactoryServiceAndMethod((string) $factoryClassOrService, $method);
100101
}
@@ -164,4 +165,15 @@ private function validateFactoryServiceAndMethod($factoryServiceId, $factoryMeth
164165

165166
$this->validateFactoryClassAndMethod($factoryClass, $factoryMethod);
166167
}
168+
169+
private function validateFactoryServiceDefinitionAndMethod(Definition $factoryServiceDefinition, $factoryMethod)
170+
{
171+
if (!$factoryMethod) {
172+
throw new MissingFactoryMethodException();
173+
}
174+
175+
$factoryClass = $factoryServiceDefinition->getClass();
176+
177+
$this->validateFactoryClassAndMethod($factoryClass, $factoryMethod);
178+
}
167179
}

Tests/Functional/Fixtures/reported_problems.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ services:
77
password: "password"
88
calls:
99
- [setAttribute, [3, 2]]
10+
11+
# Issue 33: https://github.com/matthiasnoback/symfony-service-definition-validator/issues/33
12+
service_created_by_nonpublic_factory:
13+
class: stdClass
14+
factory: ["@nonpublic_factory", "create"]
15+
arguments:
16+
- required_argument
17+
18+
nonpublic_factory:
19+
class: Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures\Factory
20+
public: false

Tests/ServiceDefinitionValidatorTest.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,102 @@ public function ifFactoryMethodDoesNotExistOnFactoryServiceFails()
228228
$validator->validate($definition);
229229
}
230230

231+
/**
232+
* @test
233+
*/
234+
public function factoryCanBeProvidedByServiceDefinition()
235+
{
236+
if (!method_exists('Symfony\Component\DependencyInjection\Definition', 'getFactory')) {
237+
$this->markTestSkipped('Factory can be provided by service definition since Symfony 2.6');
238+
}
239+
240+
$factoryDefinition = new Definition('Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\FactoryClass');
241+
$definition = new Definition('stdClass');
242+
$definition->setFactory(array($factoryDefinition, 'create'));
243+
244+
$containerBuilder = new ContainerBuilder();
245+
$validator = new ServiceDefinitionValidator(
246+
$containerBuilder,
247+
$this->createMockDefinitionArgumentsValidator(),
248+
$this->createMockMethodCallsValidator()
249+
);
250+
251+
$validator->validate($definition);
252+
}
253+
254+
/**
255+
* @test
256+
*/
257+
public function ifFactoryProvidedByServiceDefinitionClassDoesNotExistFails()
258+
{
259+
if (!method_exists('Symfony\Component\DependencyInjection\Definition', 'getFactory')) {
260+
$this->markTestSkipped('Factory can be provided by service definition since Symfony 2.6');
261+
}
262+
263+
$factoryDefinition = new Definition('Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\MissingFactoryClass');
264+
$definition = new Definition('stdClass');
265+
$definition->setFactory(array($factoryDefinition, 'create'));
266+
267+
$containerBuilder = new ContainerBuilder();
268+
$validator = new ServiceDefinitionValidator(
269+
$containerBuilder,
270+
$this->createMockDefinitionArgumentsValidator(),
271+
$this->createMockMethodCallsValidator()
272+
);
273+
274+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\ClassNotFoundException');
275+
$validator->validate($definition);
276+
}
277+
278+
/**
279+
* @test
280+
*/
281+
public function ifFactoryProvidedByServiceDefinitionSpecifiedWithoutFactoryMethodFails()
282+
{
283+
if (!method_exists('Symfony\Component\DependencyInjection\Definition', 'getFactory')) {
284+
$this->markTestSkipped('Factory can be provided by service definition since Symfony 2.6');
285+
}
286+
287+
$factoryDefinition = new Definition('Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\FactoryClass');
288+
$definition = new Definition('stdClass');
289+
$definition->setFactory(array($factoryDefinition, ''));
290+
291+
$containerBuilder = new ContainerBuilder();
292+
$validator = new ServiceDefinitionValidator(
293+
$containerBuilder,
294+
$this->createMockDefinitionArgumentsValidator(),
295+
$this->createMockMethodCallsValidator()
296+
);
297+
298+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\MissingFactoryMethodException');
299+
$validator->validate($definition);
300+
}
301+
302+
/**
303+
* @test
304+
*/
305+
public function ifFactoryMethodDoesNotExistOnFactoryServiceProvidedByDefinitionFails()
306+
{
307+
if (!method_exists('Symfony\Component\DependencyInjection\Definition', 'getFactory')) {
308+
$this->markTestSkipped('Factory can be provided by service definition since Symfony 2.6');
309+
}
310+
311+
$factoryDefinition = new Definition('Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\FactoryClass');
312+
$definition = new Definition('stdClass');
313+
$definition->setFactory(array($factoryDefinition, 'nonExistingFactoryMethod'));
314+
315+
$containerBuilder = new ContainerBuilder();
316+
$validator = new ServiceDefinitionValidator(
317+
$containerBuilder,
318+
$this->createMockDefinitionArgumentsValidator(),
319+
$this->createMockMethodCallsValidator()
320+
);
321+
322+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\MethodNotFoundException');
323+
$validator->validate($definition);
324+
}
325+
326+
231327
private function getNonExistingClassName()
232328
{
233329
return md5(rand(1, 999));

0 commit comments

Comments
 (0)