Skip to content

Commit 0b0388e

Browse files
Fixed some false negatives, renamed some classes
1 parent 70bc4fb commit 0b0388e

23 files changed

+166
-80
lines changed

ArgumentValidator.php

+24-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException;
66
use Symfony\Component\DependencyInjection\ContainerBuilder;
7+
use Symfony\Component\DependencyInjection\Definition;
78
use Symfony\Component\DependencyInjection\Reference;
89

910
class ArgumentValidator implements ArgumentValidatorInterface
@@ -14,19 +15,24 @@ class ArgumentValidator implements ArgumentValidatorInterface
1415
public function __construct(
1516
ContainerBuilder $containerBuilder,
1617
ResultingClassResolverInterface $resultingClassResolver
17-
)
18-
{
18+
) {
1919
$this->containerBuilder = $containerBuilder;
2020
$this->resultingClassResolver = $resultingClassResolver;
2121
}
2222

2323
public function validate(\ReflectionParameter $parameter, $argument)
2424
{
25+
if ($argument === null && $parameter->allowsNull()) {
26+
return;
27+
}
28+
2529
if ($parameter->isArray()) {
2630
$this->validateArrayArgument($argument);
2731
} elseif ($parameter->getClass()) {
2832
$this->validateObjectArgument($parameter->getClass()->getName(), $argument);
2933
}
34+
35+
// other argument don't need to be or can't be validated
3036
}
3137

3238
private function validateArrayArgument($argument)
@@ -41,18 +47,30 @@ private function validateArrayArgument($argument)
4147

4248
private function validateObjectArgument($className, $argument)
4349
{
44-
if (!($argument instanceof Reference)) {
50+
if ($argument instanceof Reference) {
51+
$this->validateReferenceArgument($className, $argument);
52+
} elseif ($argument instanceof Definition) {
53+
$this->validateDefinitionArgument($className, $argument);
54+
} else {
4555
throw new TypeHintMismatchException(sprintf(
46-
'Type-hint "%s" requires this argument to be an instance of Symfony\Component\DependencyInjection\Reference',
56+
'Type-hint "%s" requires this argument to be a reference to a service or an inline service definition',
4757
$className
4858
));
4959
}
60+
}
5061

62+
private function validateReferenceArgument($className, Reference $reference)
63+
{
5164
// the __toString method of a Reference is the referenced service id
52-
$referencedServiceId = (string)$argument;
65+
$referencedServiceId = (string)$reference;
5366
$definition = $this->containerBuilder->findDefinition($referencedServiceId);
5467
// we don't have to check if the definition exists, since the ContainerBuilder itself does that already
5568

69+
$this->validateDefinitionArgument($className, $definition);
70+
}
71+
72+
private function validateDefinitionArgument($className, Definition $definition)
73+
{
5674
$resultingClass = $this->resultingClassResolver->resolve($definition);
5775
if ($resultingClass === null) {
5876
return;
@@ -65,7 +83,7 @@ private function validateObjectArgument($className, $argument)
6583
$reflectionClass = new \ReflectionClass($resultingClass);
6684
if (!$reflectionClass->isSubclassOf($className)) {
6785
throw new TypeHintMismatchException(sprintf(
68-
'Argument with type-hint "%s" is a reference to a service of class "%s"',
86+
'Argument for type-hint "%s" should point to a service of class "%s"',
6987
$className,
7088
$resultingClass
7189
));

ArgumentsValidator.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public function validate(\ReflectionMethod $method, array $arguments)
1717
{
1818
foreach ($method->getParameters() as $parameterNumber => $parameter) {
1919
$argument = $this->resolveArgument($parameterNumber, $parameter, $arguments);
20+
2021
$this->argumentValidator->validate($parameter, $argument);
2122
}
2223
}
@@ -31,7 +32,8 @@ private function resolveArgument($parameterIndex, \ReflectionParameter $paramete
3132
}
3233

3334
if (!$parameter->isOptional()) {
34-
throw new MissingRequiredArgumentException($parameter->getDeclaringClass()->getName(), $parameter->getName());
35+
throw new MissingRequiredArgumentException($parameter->getDeclaringClass()->getName(), $parameter->getName(
36+
));
3537
}
3638

3739
return null;

BatchServiceDefinitionValidator.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ class BatchServiceDefinitionValidator implements BatchServiceDefinitionValidator
1414
public function __construct(
1515
ServiceDefinitionValidatorInterface $serviceDefinitionValidator,
1616
ValidationErrorFactoryInterface $validationErrorFactory
17-
)
18-
{
17+
) {
1918
$this->serviceDefinitionValidator = $serviceDefinitionValidator;
2019
$this->validationErrorFactory = $validationErrorFactory;
2120
}

ConstructorResolver.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ class ConstructorResolver implements ConstructorResolverInterface
1515
public function __construct(
1616
ContainerBuilder $containerBuilder,
1717
ResultingClassResolverInterface $resultingClassResolver
18-
)
19-
{
18+
) {
2019
$this->containerBuilder = $containerBuilder;
2120
$this->resultingClassResolver = $resultingClassResolver;
2221
}

MethodCallsValidator.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ class MethodCallsValidator implements MethodCallsValidatorInterface
1313
public function __construct(
1414
ResultingClassResolverInterface $resultingClassResolver,
1515
ArgumentsValidatorInterface $argumentsValidator
16-
)
17-
{
16+
) {
1817
$this->resultingClassResolver = $resultingClassResolver;
1918
$this->argumentsValidator = $argumentsValidator;
2019
}

ServiceDefinitionValidator.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ public function __construct(
2020
ContainerBuilder $containerBuilder,
2121
DefinitionArgumentsValidatorInterface $definitionArgumentsValidator,
2222
MethodCallsValidatorInterface $methodCallsValidator
23-
)
24-
{
23+
) {
2524
$this->containerBuilder = $containerBuilder;
2625
$this->definitionArgumentsValidator = $definitionArgumentsValidator;
2726
$this->methodCallsValidator = $methodCallsValidator;

ServiceDefinitionValidatorFactory.php

-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,4 @@ public function create(ContainerBuilder $containerBuilder)
2323

2424
return $validator;
2525
}
26-
2726
}

TODO

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
- Rewrite tests to verify positive results instead of just catching negative results.

Tests/ArgumentValidatorTest.php

+39-14
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,50 @@
99

1010
class ArgumentValidatorTest extends \PHPUnit_Framework_TestCase
1111
{
12-
public function testFailsWhenParameterHasTypeHintButNoReferenceWasProvidedAsArgument()
12+
private $containerBuilder;
13+
14+
protected function setUp()
15+
{
16+
$this->containerBuilder = new ContainerBuilder();
17+
}
18+
19+
public function testFailsWhenParameterHasTypeHintButNoReferenceOrDefinitionWasProvidedAsArgument()
20+
{
21+
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithTypeHintedConstructorArgument';
22+
23+
$validator = new ArgumentValidator($this->containerBuilder, $this->createMockResultingClassResolver());
24+
25+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException', 'reference');
26+
$validator->validate(new \ReflectionParameter(array($class, '__construct'), 'expected'), new \stdClass());
27+
}
28+
29+
public function testFailsWhenParameterHasTypeHintForObjectButArgumentIsDefinitionForServiceOfWrongType()
1330
{
14-
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithTypeHintedDateTimeConstructorArgument';
15-
$containerBuilder = new ContainerBuilder();
31+
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithTypeHintedConstructorArgument';
32+
$this->containerBuilder = new ContainerBuilder();
1633

17-
$validator = new ArgumentValidator($containerBuilder, $this->createMockResultingClassResolver());
34+
$inlineDefinition = new Definition();
35+
36+
$resultingClassResolver = $this->createMockResultingClassResolver();
37+
$resultingClassResolver
38+
->expects($this->once())
39+
->method('resolve')
40+
->with($inlineDefinition)
41+
->will($this->returnValue('Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\WrongClass'));
42+
$validator = new ArgumentValidator($this->containerBuilder, $resultingClassResolver);
1843

19-
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException', 'Reference');
20-
$validator->validate(new \ReflectionParameter(array($class, '__construct'), 'date'), new \stdClass());
44+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException', 'ExpectedClass');
45+
$validator->validate(new \ReflectionParameter(array($class, '__construct'), 'expected'), $inlineDefinition);
2146
}
2247

23-
public function testFailsWhenParameterHasTypeHintButArgumentIsReferenceToServiceOfWrongTypeWasProvided()
48+
public function testFailsWhenParameterHasTypeHintForObjectButArgumentIsReferenceToServiceOfWrongType()
2449
{
25-
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithTypeHintedDateTimeConstructorArgument';
26-
$containerBuilder = new ContainerBuilder();
50+
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithTypeHintedConstructorArgument';
51+
$this->containerBuilder = new ContainerBuilder();
2752
$definition = new Definition();
28-
$containerBuilder->setDefinition('referenced_service', $definition);
53+
$this->containerBuilder->setDefinition('referenced_service', $definition);
2954

30-
$parameter = new \ReflectionParameter(array($class, '__construct'), 'date');
55+
$parameter = new \ReflectionParameter(array($class, '__construct'), 'expected');
3156
$argument = new Reference('referenced_service');
3257

3358
$resultingClassResolver = $this->createMockResultingClassResolver();
@@ -36,16 +61,16 @@ public function testFailsWhenParameterHasTypeHintButArgumentIsReferenceToService
3661
->method('resolve')
3762
->with($definition)
3863
->will($this->returnValue('stdClass'));
39-
$validator = new ArgumentValidator($containerBuilder, $resultingClassResolver);
64+
$validator = new ArgumentValidator($this->containerBuilder, $resultingClassResolver);
4065

41-
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException', 'DateTime');
66+
$this->setExpectedException('Matthias\SymfonyServiceDefinitionValidator\Exception\TypeHintMismatchException', 'ExpectedClass');
4267

4368
$validator->validate($parameter, $argument);
4469
}
4570

4671
public function testFailsWhenParameterHasArrayTypeHintButArgumentIsNotArray()
4772
{
48-
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithArrayConstructorArgument';
73+
$class = 'Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures\ClassWithRequiredArrayConstructorArgument';
4974

5075
$parameter = new \ReflectionParameter(array($class, '__construct'), 'options');
5176
$argument = 'string';

Tests/Fixtures/ClassWithArrayConstructorArgument.php renamed to Tests/Fixtures/ClassWithRequiredArrayConstructorArgument.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures;
44

5-
class ClassWithArrayConstructorArgument
5+
class ClassWithRequiredArrayConstructorArgument
66
{
77
public function __construct(array $options)
88
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures;
4+
5+
class ClassWithTypeHintedConstructorArgument
6+
{
7+
public function __construct(ExpectedClass $expected)
8+
{
9+
}
10+
}

Tests/Fixtures/ClassWithTypeHintedDateTimeConstructorArgument.php

-10
This file was deleted.

Tests/Fixtures/ExpectedClass.php

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures;
4+
5+
class ExpectedClass
6+
{
7+
}

Tests/Fixtures/WrongClass.php

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Fixtures;
4+
5+
class WrongClass
6+
{
7+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures;
4+
5+
class Catalogue
6+
{
7+
}

Tests/Functional/Fixtures/Factory.php

-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,5 @@ class Factory
66
{
77
public function create($argument1)
88
{
9-
109
}
1110
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures;
4+
5+
class MailManager
6+
{
7+
public function __construct(Mailer $mailer = null)
8+
{
9+
}
10+
}

Tests/Functional/Fixtures/Product.php renamed to Tests/Functional/Fixtures/Mailer.php

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22

33
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures;
44

5-
class Product
5+
class Mailer
66
{
7-
public function __construct(Price $price)
7+
public function __construct(Transport $transport)
88
{
9-
109
}
1110
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures;
4+
5+
class Translator
6+
{
7+
public function __construct(Catalogue $catalogue)
8+
{
9+
}
10+
}

Tests/Functional/Fixtures/Price.php renamed to Tests/Functional/Fixtures/Transport.php

+3-5
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
namespace Matthias\SymfonyServiceDefinitionValidator\Tests\Functional\Fixtures;
44

5-
class Price
5+
class Transport
66
{
7-
public function __construct($currency = 'euro')
7+
public function __construct($username = 'root')
88
{
9-
109
}
1110

12-
public function setCurrency($currency)
11+
public function setUsername($username)
1312
{
14-
1513
}
1614
}

0 commit comments

Comments
 (0)