Skip to content

Commit

Permalink
Adding support for resolving Union types.
Browse files Browse the repository at this point in the history
  • Loading branch information
brentscheffler committed Mar 14, 2023
1 parent fff9712 commit 1de3afb
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 43 deletions.
95 changes: 54 additions & 41 deletions src/Resolve.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use ReflectionClass;
use ReflectionException;
use ReflectionFunction;
use ReflectionNamedType;
use ReflectionObject;
use ReflectionParameter;

Expand Down Expand Up @@ -74,59 +75,71 @@ function(ReflectionParameter $reflectionParameter) use ($container, $parameters)
return $parameters[$parameter_name];
}

$parameter_type = $reflectionParameter->getType();
$reflectionType = $reflectionParameter->getType();

if( $parameter_type instanceof \ReflectionNamedType === false ) {
throw new ParameterResolutionException("Cannot resolve union or intersection types");
if( empty($reflectionType) ){
throw new ParameterResolutionException("Cannot resolve parameter with no type.");
}

/**
* Check container and parameters for a match by type.
*/
if( !$parameter_type->isBuiltin() ) {
if( $reflectionType instanceof \ReflectionIntersectionType ){
throw new ParameterResolutionException("Cannot resolve intersection types.");
}
elseif( $reflectionType instanceof \ReflectionNamedType ){
$reflectionType = [$reflectionType];
}
elseif( $reflectionType instanceof \ReflectionUnionType ){
$reflectionType = $reflectionType->getTypes();
}

if( $container && $container->has($parameter_type->getName()) ){
return $container->get($parameter_type->getName());
}
foreach( $reflectionType as $parameter_type ){
/**
* Check container and parameters for a match by type.
*/
if( !$parameter_type->isBuiltin() ) {

// Try to find in the parameters supplied
$match = \array_filter(
$parameters,
function($parameter) use ($parameter_type): bool {
$parameter_type_name = $parameter_type->getName();
return $parameter instanceof $parameter_type_name;
if( $container && $container->has($parameter_type->getName()) ){
return $container->get($parameter_type->getName());
}
);

if( $match ){
return $match[
\array_keys($match)[0]
];
}
// Try to find in the parameters supplied
$match = \array_filter(
$parameters,
function($parameter) use ($parameter_type): bool {
$parameter_type_name = $parameter_type->getName();
return $parameter instanceof $parameter_type_name;
}
);

try {
if( $match ){
return $match[
\array_keys($match)[0]
];
}

return $this->make(
$parameter_type->getName(),
$container,
$parameters
);
try {

return $this->make(
$parameter_type->getName(),
$container,
$parameters
);
}
catch( \Exception $exception ){}
}
catch( \Exception $exception ){}
}

/**
* If a default value is defined, use that, including a null value.
*/
if( $reflectionParameter->isDefaultValueAvailable() ){
return $reflectionParameter->getDefaultValue();
}
elseif( $reflectionParameter->allowsNull() ){
return null;
}
/**
* If a default value is defined, use that, including a null value.
*/
if( $reflectionParameter->isDefaultValueAvailable() ){
return $reflectionParameter->getDefaultValue();
}
elseif( $reflectionParameter->allowsNull() ){
return null;
}

if( !empty($exception) ){
throw $exception;
if( !empty($exception) ){
throw $exception;
}
}

throw new ParameterResolutionException("Cannot resolve parameter \"{$parameter_name}\".");
Expand Down
34 changes: 32 additions & 2 deletions tests/ResolveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ public function test_resolve_reflection_parameters_with_making_class_with_constr
);
}

public function test_resolve_reflection_parameters_with_non_reflection_named_type_throws_parameter_resolution_exception(): void
public function test_resolve_reflection_parameters_with_union_type(): void
{
$resolve = new class {
use Resolve;
Expand All @@ -572,7 +572,37 @@ public function test_resolve_reflection_parameters_with_non_reflection_named_typ
$reflectionMethod = $reflectionClass->getMethod("resolveReflectionParameters");
$reflectionMethod->setAccessible(true);

$callable = function(DateTime|DateTimeImmutable $dateTime): void {
$callable = function(DateTime|DateTimeImmutable $dateTime): string {
return "The date is now: " . $dateTime->format("c");
};

$dateTime = new DateTimeImmutable("2020-01-28T12:00:01-08:00");

$reflectionFunction = new ReflectionFunction($callable);
$result = $reflectionMethod->invoke(
$resolve,
$reflectionFunction->getParameters(),
null,
["dateTime" => $dateTime]
);

$this->assertSame(
$dateTime,
$result[0]
);
}

public function test_resolve_reflection_parameters_with_intersection_type_throws_parameter_resolution_exception(): void
{
$resolve = new class {
use Resolve;
};

$reflectionClass = new ReflectionClass($resolve);
$reflectionMethod = $reflectionClass->getMethod("resolveReflectionParameters");
$reflectionMethod->setAccessible(true);

$callable = function(DateTime&DateTimeImmutable $dateTime): void {
echo "The date is now: " . $dateTime;
};

Expand Down

0 comments on commit 1de3afb

Please sign in to comment.