Skip to content

Commit

Permalink
Fixed a few bugs with optional references, added unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
joshiausdemwald committed Jun 22, 2011
1 parent a1ebb2f commit 828dd83
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 12 deletions.
Expand Up @@ -52,6 +52,12 @@ public function injectService(\ReflectionClass $class)
return $this->doInject($class);
}

/**
* Does the injection.
*
* @param \ReflectionClass $class
* @return String $service_Id: The services id´s.
*/
protected function doInject(\ReflectionClass $class)
{
if($this->hasAnnotation(Injector::ANNOTATION_SERVICE))
Expand Down Expand Up @@ -158,6 +164,8 @@ protected function doInject(\ReflectionClass $class)
*/
protected function createDefinition(\ReflectionClass $class)
{
$definition = null;

if(false !== ($parentClass = $class->getParentClass()))
{
$parent_service_id = $this->injectService($parentClass);
Expand Down
Expand Up @@ -92,7 +92,7 @@ public function guessArgumentsForMethodSignature(\ReflectionMethod $method)
if($annotationsMap->hasHint($i))
{
$is_optional = $annotationsMap->getIsOptional($i);

$resource_name = $annotationsMap->getResourceName($i);

// NO MATCHING SERVICE PARAMETER FOUND, CHECK FOR SCALAR VALUE
Expand All @@ -104,7 +104,10 @@ public function guessArgumentsForMethodSignature(\ReflectionMethod $method)
}
catch(\InvalidArgumentException $e)
{
throw new UnresolvedReferenceException(sprintf('Argument "$%s" on method "%s::%s()" could not be resolved: Service definition "%s" not found. Please provide a valid service id.', $parameter->getName(), $method->getDeclaringClass()->getName(), $method->getName(), $resource_name), null, $e);
if( ! $is_optional)
{
throw new UnresolvedReferenceException(sprintf('Argument "$%s" on method "%s::%s()" could not be resolved: Service definition "%s" not found. Please provide a valid service id.', $parameter->getName(), $method->getDeclaringClass()->getName(), $method->getName(), $resource_name), null, $e);
}
}

$arguments[] = $this->createReference($resource_name, $this->getBehaviour($parameter, $is_optional), true);
Expand Down Expand Up @@ -153,17 +156,17 @@ public function guessArgumentsForMethodSignature(\ReflectionMethod $method)
else
{
$service_id = $this->classnameMapper->resolveService($type->getName());

if (null === $service_id)
{
throw new UnresolvedReferenceException(sprintf('Argument "$%s" at method signature of "%s::%s()" could not be resolved: There is no service that matches the arguments typename. Please provide a valid service id.', $parameter->getName(), $method->getDeclaringClass()->getName(), $method->getName(), $type->getName()));
}


if (false === $service_id)
{
throw new AmbiguousServiceReferenceException(sprintf('Argument "$%s" of type "%s" at method signature of "%s::%s()" could not be distinctly allocated: There is more than on services that rely on the given type. Please provide a valid, distinct service id.', $parameter->getName(), $type->getName(), $method->getDeclaringClass()->getName(), $method->getName()));
}

if (null === $service_id && ! $parameter->isOptional())
{
throw new UnresolvedReferenceException(sprintf('Argument "$%s" at method signature of "%s::%s()" could not be resolved: There is no service that matches the arguments typename. Please provide a valid service id.', $parameter->getName(), $method->getDeclaringClass()->getName(), $method->getName(), $type->getName()));
}

$arguments[] = $this->createReference($service_id, $this->getBehaviour($parameter), true);
}
}
Expand All @@ -185,7 +188,7 @@ protected function getBehaviour(\ReflectionParameter $parameter, $is_optional =
{
if(null === $is_optional || $is_optional)
{
if($parameter->isOptional() || $parameter->isDefaultValueAvailable())
if($parameter->isOptional())
{
return Container::IGNORE_ON_INVALID_REFERENCE;
}
Expand Down
Expand Up @@ -139,20 +139,26 @@ protected function process(Definition $definition, \Reflector $property)
}
catch(\InvalidArgumentException $e)
{
throw new UnresolvedReferenceException(sprintf('Instance property "%s::$%s" could not be resolved: Service definition "%s" not found. Please provide a valid service id.', $property->getDeclaringClass()->getName(), $property->getName(), $resource_name), null, $e);
if( ! $is_optional)
{
throw new UnresolvedReferenceException(sprintf('Instance property "%s::$%s" could not be resolved: Service definition "%s" not found. Please provide a valid service id.', $property->getDeclaringClass()->getName(), $property->getName(), $resource_name), null, $e);
}
}

$inject = $this->createReference($resource_name, $is_optional, true);
}
elseif($annotationMap->getIsParameter(0))
{
if($this->container->hasParameter($resource_name) && ! $is_optional)
if($this->container->hasParameter($resource_name))
{
$inject = new Parameter($resource_name);
}
else
{
throw new UnresolvedParamterException(sprintf('Instance property "%s::$%s" could not be resolved: Container parameter "%s" not found. Please provide a valid parameter name.', $property->getDeclaringClass()->getName(), $property->getName(), $resource_name));
if( ! $is_optional)
{
throw new UnresolvedParamterException(sprintf('Instance property "%s::$%s" could not be resolved: Container parameter "%s" not found. Please provide a valid parameter name.', $property->getDeclaringClass()->getName(), $property->getName(), $resource_name));
}
}
}

Expand Down
Expand Up @@ -233,6 +233,119 @@ public function testDependencyResolving(array $files)
);
}

/**
*
*/
public function failOptionalArguments()
{
$container = new \Symfony\Component\DependencyInjection\ContainerBuilder();

$reader = new \Ifschleife\Bundle\AutowiringBundle\Annotation\AnnotationReaderDecorator;

$serviceBuilder = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\ServiceBuilder(
new \Ifschleife\Bundle\AutowiringBundle\DependencyInjection\Loader\AnnotatedFileLoader(
$container,
new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\ContainerInjector($container,
$reader
),
new \Symfony\Component\Config\FileLocator(),
new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Parser\PhpParser()
));

$serviceBuilder->setFiles(array(__DIR__ . '/../Fixtures/OptionalInjectionFailclass.php'));

$serviceBuilder->build();

$classnameMapper = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\ClassnameMapper($container);

$propertyInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\PropertyInjector($container, $reader);
$propertyInjector->setWireByName(true);
$propertyInjector->setServiceNameSuffix('Service');

$constructorInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\ConstructorInjector($container, $reader, $classnameMapper);
$constructorInjector->setWireByType(true);

$setterInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\SetterInjector($container, $reader, $classnameMapper);
$setterInjector->setWireByType(true);

// ContainerBuilder $container, ClassnameMapper $classname_mapper, PropertyInjector $property_injector, ConstructorInjector $constructor_injector, SetterInjector $setter_injector
$dependencyResolver = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\DependencyResolver(
$container,
$classnameMapper,
$propertyInjector,
$constructorInjector,
$setterInjector
);

try
{
$dependencyResolver->resolve();
}
catch(Exception $e)
{
$this->assertInstanceOf('Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\UnresolvedReferenceException', $e);
}

}

/**
* @dataProvider optionalFiles
*/
public function testOptionalArguments($file)
{
$container = new \Symfony\Component\DependencyInjection\ContainerBuilder();

$reader = new \Ifschleife\Bundle\AutowiringBundle\Annotation\AnnotationReaderDecorator;

$serviceBuilder = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\ServiceBuilder(
new \Ifschleife\Bundle\AutowiringBundle\DependencyInjection\Loader\AnnotatedFileLoader(
$container,
new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\ContainerInjector($container,
$reader
),
new \Symfony\Component\Config\FileLocator(),
new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Parser\PhpParser()
));

$serviceBuilder->setFiles(array($file));

$serviceBuilder->build();

$classnameMapper = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\ClassnameMapper($container);

$propertyInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\PropertyInjector($container, $reader);
$propertyInjector->setWireByName(true);
$propertyInjector->setServiceNameSuffix('Service');

$constructorInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\ConstructorInjector($container, $reader, $classnameMapper);
$constructorInjector->setWireByType(true);

$setterInjector = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\Injector\SetterInjector($container, $reader, $classnameMapper);
$setterInjector->setWireByType(true);

// ContainerBuilder $container, ClassnameMapper $classname_mapper, PropertyInjector $property_injector, ConstructorInjector $constructor_injector, SetterInjector $setter_injector
$dependencyResolver = new \Ifschleife\Bundle\AutowiringBundle\Autowiring\DependencyResolver(
$container,
$classnameMapper,
$propertyInjector,
$constructorInjector,
$setterInjector
);

$dependencyResolver->resolve();

$this->assertInstanceOf('Ifschleife\Bundle\AutowiringBundle\Tests\Fixtures\OptionalInjectionTestclass', $container->get('autowiring.optional_injection_testclass'));
}

function optionalFiles()
{
return array(
array(
__DIR__ . '/../Fixtures/OptionalInjectionTestclass.php'
)
);
}

function files()
{
return array(
Expand Down
@@ -0,0 +1,45 @@
<?php
/**
* Copyright (c) 2011 Johannes Heinen <johannes.heinen@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

namespace Ifschleife\Bundle\AutowiringBundle\Tests\Fixtures;

use Ifschleife\Bundle\AutowiringBundle\Annotations\Service;
use Ifschleife\Bundle\AutowiringBundle\Annotations\Inject;

/**
* OptionalInjectionTestclass
*
* @author joshi
* @Service("autowiring.optional_injection_testclass")
*/
class OptionalInjectionFailclass
{
/**
* @param Testservice $testservice
* @Inject
*/
public function __construct(Testservice $testservice)
{

}
}
@@ -0,0 +1,69 @@
<?php
/**
* Copyright (c) 2011 Johannes Heinen <johannes.heinen@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

namespace Ifschleife\Bundle\AutowiringBundle\Tests\Fixtures;

use Ifschleife\Bundle\AutowiringBundle\Annotations\Service;
use Ifschleife\Bundle\AutowiringBundle\Annotations\Inject;

/**
* OptionalInjectionTestclass
*
* @author joshi
* @Service("autowiring.optional_injection_testclass")
*/
class OptionalInjectionTestclass
{
/**
* @Inject("@?does.not.exist")
*/
protected $testService;

/**
* @param Testservice $testservice
* @Inject
*/
public function __construct(Testservice $testservice = null)
{

}

/**
*
* @param Testservice $testservice
* @Inject
*/
public function setOptionalService(Testservice $testservice = null)
{

}

/**
* @param Testservice $testservice
* @Inject("@?Does.Not.Exist")
*/
public function setOptionalService2(Testservice $testservice = null)
{

}
}

0 comments on commit 828dd83

Please sign in to comment.