Skip to content

Commit

Permalink
✨ [#708] Re-introduce feature about supporting target method attribut…
Browse files Browse the repository at this point in the history
…es for resolving parameter annotations
  • Loading branch information
andrew-demb committed Nov 17, 2024
1 parent 0f1a112 commit f5cd4b5
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 1 deletion.
26 changes: 25 additions & 1 deletion src/AnnotationReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
use TheCodingMachine\GraphQLite\Annotations\Type;
use TheCodingMachine\GraphQLite\Annotations\TypeInterface;

use function array_diff_key;
use function array_filter;
use function array_key_exists;
use function array_map;
use function array_merge;
use function assert;
use function count;
use function get_class;
use function is_a;
use function reset;

Expand Down Expand Up @@ -248,11 +250,33 @@ public function getParameterAnnotationsPerParameter(array $refParameters): array
if (empty($refParameters)) {
return [];
}
$firstParam = reset($refParameters);

/** @var array<string, array<int,ParameterAnnotationInterface>> $parameterAnnotationsPerParameter */
$parameterAnnotationsPerParameter = [];

// resolve parameter annotations targeted to method
$firstParam = reset($refParameters);
$method = $firstParam->getDeclaringFunction();
assert($method instanceof ReflectionMethod);

$parameterAnnotations = $this->getMethodAnnotations($method, ParameterAnnotationInterface::class);
foreach ($parameterAnnotations as $parameterAnnotation) {
$parameterAnnotationsPerParameter[$parameterAnnotation->getTarget()][] = $parameterAnnotation;
}

// Let's check that the referenced parameters actually do exist:
$parametersByKey = [];
foreach ($refParameters as $refParameter) {
$parametersByKey[$refParameter->getName()] = true;
}
$diff = array_diff_key($parameterAnnotationsPerParameter, $parametersByKey);
if (count($diff) > 0) {
foreach ($diff as $parameterName => $parameterAnnotations) {
throw InvalidParameterException::parameterNotFound($parameterName, get_class($parameterAnnotations[0]), $method);
}
}

// resolve parameter annotations targeted to parameter
foreach ($refParameters as $refParameter) {
$attributes = $refParameter->getAttributes();
$parameterAnnotationsPerParameter[$refParameter->getName()] = [...$parameterAnnotationsPerParameter[$refParameter->getName()] ??
Expand Down
5 changes: 5 additions & 0 deletions src/Annotations/Exceptions/InvalidParameterException.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

class InvalidParameterException extends BadMethodCallException
{
public static function parameterNotFound(string $parameter, string $annotationClass, ReflectionMethod $reflectionMethod): self
{
return new self(sprintf('Parameter "%s" declared in annotation "%s" of method "%s::%s()" does not exist.', $parameter, $annotationClass, $reflectionMethod->getDeclaringClass()->getName(), $reflectionMethod->getName()));
}

public static function parameterNotFoundFromSourceField(string $parameter, string $annotationClass, ReflectionMethod $reflectionMethod): self
{
return new self(sprintf('Could not find parameter "%s" declared in annotation "%s". This annotation is itself declared in a SourceField attribute targeting resolver "%s::%s()".', $parameter, $annotationClass, $reflectionMethod->getDeclaringClass()->getName(), $reflectionMethod->getName()));
Expand Down
15 changes: 15 additions & 0 deletions tests/AnnotationReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidClassAnnotation;
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidExtendTypeAnnotation;
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidTypeAnnotation;
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithTargetMethodParameterAnnotation;
use TheCodingMachine\GraphQLite\Fixtures\Annotations\TargetMethodParameterAnnotation;
use TheCodingMachine\GraphQLite\Fixtures\Attributes\TestType;

class AnnotationReaderTest extends TestCase
Expand Down Expand Up @@ -126,6 +128,19 @@ public function testPhp8AttributeParameterAnnotations(): void
$this->assertInstanceOf(Autowire::class, $parameterAnnotations['dao']->getAnnotationByType(Autowire::class));
}

/**
* This functionality can be dropped with next major release (8.0) with added explicit deprecations before release.
*/
public function testPhp8AttributeParameterAnnotationsForTargetMethod(): void
{
$annotationReader = new AnnotationReader();

$parameterAnnotations = $annotationReader->getParameterAnnotationsPerParameter((new ReflectionMethod(ClassWithTargetMethodParameterAnnotation::class, 'method'))->getParameters());

$this->assertInstanceOf(TargetMethodParameterAnnotation::class, $parameterAnnotations['bar']->getAnnotationByType(TargetMethodParameterAnnotation::class));
}

/** @noinspection PhpUnusedPrivateMethodInspection Used in {@see testPhp8AttributeParameterAnnotations} */
private function method1(
#[Autowire('myService')]
$dao,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace TheCodingMachine\GraphQLite\Fixtures\Annotations;

use stdClass;

/** @internal */
final class ClassWithTargetMethodParameterAnnotation
{
#[TargetMethodParameterAnnotation(target: 'bar')]
public function method(stdClass $bar): void
{
}
}
20 changes: 20 additions & 0 deletions tests/Fixtures/Annotations/TargetMethodParameterAnnotation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace TheCodingMachine\GraphQLite\Fixtures\Annotations;

use TheCodingMachine\GraphQLite\Annotations\ParameterAnnotationInterface;

#[\Attribute(\Attribute::TARGET_METHOD)]
final class TargetMethodParameterAnnotation implements ParameterAnnotationInterface
{
public function __construct(private readonly string $target)
{
}

public function getTarget(): string
{
return $this->target;
}
}

0 comments on commit f5cd4b5

Please sign in to comment.