Skip to content

Commit f5cd4b5

Browse files
committed
✨ [#708] Re-introduce feature about supporting target method attributes for resolving parameter annotations
1 parent 0f1a112 commit f5cd4b5

5 files changed

+81
-1
lines changed

src/AnnotationReader.php

+25-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
use TheCodingMachine\GraphQLite\Annotations\Type;
2525
use TheCodingMachine\GraphQLite\Annotations\TypeInterface;
2626

27+
use function array_diff_key;
2728
use function array_filter;
2829
use function array_key_exists;
2930
use function array_map;
3031
use function array_merge;
3132
use function assert;
3233
use function count;
34+
use function get_class;
3335
use function is_a;
3436
use function reset;
3537

@@ -248,11 +250,33 @@ public function getParameterAnnotationsPerParameter(array $refParameters): array
248250
if (empty($refParameters)) {
249251
return [];
250252
}
251-
$firstParam = reset($refParameters);
252253

254+
/** @var array<string, array<int,ParameterAnnotationInterface>> $parameterAnnotationsPerParameter */
255+
$parameterAnnotationsPerParameter = [];
256+
257+
// resolve parameter annotations targeted to method
258+
$firstParam = reset($refParameters);
253259
$method = $firstParam->getDeclaringFunction();
254260
assert($method instanceof ReflectionMethod);
255261

262+
$parameterAnnotations = $this->getMethodAnnotations($method, ParameterAnnotationInterface::class);
263+
foreach ($parameterAnnotations as $parameterAnnotation) {
264+
$parameterAnnotationsPerParameter[$parameterAnnotation->getTarget()][] = $parameterAnnotation;
265+
}
266+
267+
// Let's check that the referenced parameters actually do exist:
268+
$parametersByKey = [];
269+
foreach ($refParameters as $refParameter) {
270+
$parametersByKey[$refParameter->getName()] = true;
271+
}
272+
$diff = array_diff_key($parameterAnnotationsPerParameter, $parametersByKey);
273+
if (count($diff) > 0) {
274+
foreach ($diff as $parameterName => $parameterAnnotations) {
275+
throw InvalidParameterException::parameterNotFound($parameterName, get_class($parameterAnnotations[0]), $method);
276+
}
277+
}
278+
279+
// resolve parameter annotations targeted to parameter
256280
foreach ($refParameters as $refParameter) {
257281
$attributes = $refParameter->getAttributes();
258282
$parameterAnnotationsPerParameter[$refParameter->getName()] = [...$parameterAnnotationsPerParameter[$refParameter->getName()] ??

src/Annotations/Exceptions/InvalidParameterException.php

+5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111

1212
class InvalidParameterException extends BadMethodCallException
1313
{
14+
public static function parameterNotFound(string $parameter, string $annotationClass, ReflectionMethod $reflectionMethod): self
15+
{
16+
return new self(sprintf('Parameter "%s" declared in annotation "%s" of method "%s::%s()" does not exist.', $parameter, $annotationClass, $reflectionMethod->getDeclaringClass()->getName(), $reflectionMethod->getName()));
17+
}
18+
1419
public static function parameterNotFoundFromSourceField(string $parameter, string $annotationClass, ReflectionMethod $reflectionMethod): self
1520
{
1621
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()));

tests/AnnotationReaderTest.php

+15
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidClassAnnotation;
1616
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidExtendTypeAnnotation;
1717
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithInvalidTypeAnnotation;
18+
use TheCodingMachine\GraphQLite\Fixtures\Annotations\ClassWithTargetMethodParameterAnnotation;
19+
use TheCodingMachine\GraphQLite\Fixtures\Annotations\TargetMethodParameterAnnotation;
1820
use TheCodingMachine\GraphQLite\Fixtures\Attributes\TestType;
1921

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

131+
/**
132+
* This functionality can be dropped with next major release (8.0) with added explicit deprecations before release.
133+
*/
134+
public function testPhp8AttributeParameterAnnotationsForTargetMethod(): void
135+
{
136+
$annotationReader = new AnnotationReader();
137+
138+
$parameterAnnotations = $annotationReader->getParameterAnnotationsPerParameter((new ReflectionMethod(ClassWithTargetMethodParameterAnnotation::class, 'method'))->getParameters());
139+
140+
$this->assertInstanceOf(TargetMethodParameterAnnotation::class, $parameterAnnotations['bar']->getAnnotationByType(TargetMethodParameterAnnotation::class));
141+
}
142+
143+
/** @noinspection PhpUnusedPrivateMethodInspection Used in {@see testPhp8AttributeParameterAnnotations} */
129144
private function method1(
130145
#[Autowire('myService')]
131146
$dao,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TheCodingMachine\GraphQLite\Fixtures\Annotations;
6+
7+
use stdClass;
8+
9+
/** @internal */
10+
final class ClassWithTargetMethodParameterAnnotation
11+
{
12+
#[TargetMethodParameterAnnotation(target: 'bar')]
13+
public function method(stdClass $bar): void
14+
{
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TheCodingMachine\GraphQLite\Fixtures\Annotations;
6+
7+
use TheCodingMachine\GraphQLite\Annotations\ParameterAnnotationInterface;
8+
9+
#[\Attribute(\Attribute::TARGET_METHOD)]
10+
final class TargetMethodParameterAnnotation implements ParameterAnnotationInterface
11+
{
12+
public function __construct(private readonly string $target)
13+
{
14+
}
15+
16+
public function getTarget(): string
17+
{
18+
return $this->target;
19+
}
20+
}

0 commit comments

Comments
 (0)