From fbae399fe7fb05cfe999ff21142343c00624ae37 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Tue, 10 Jan 2023 22:02:03 +0100 Subject: [PATCH 01/15] add attributes to annotations and the AttributeReader as JMS does --- src/Configuration/Annotation/Embedded.php | 12 + src/Configuration/Annotation/Exclusion.php | 10 + src/Configuration/Annotation/Relation.php | 12 + .../Annotation/RelationProvider.php | 10 + src/Configuration/Annotation/Route.php | 13 + .../AttributeDriver/AttributeReader.php | 89 +++++++ .../AttributeDriver/AttributeReaderTest.php | 238 ++++++++++++++++++ .../Metadata/Driver/AttributeDriverTest.php | 29 +++ tests/Hateoas/Tests/Fixtures/User.php | 33 +++ 9 files changed, 446 insertions(+) create mode 100644 src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php create mode 100644 tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php create mode 100644 tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index 9370d4b5..9acd0df7 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -4,16 +4,23 @@ namespace Hateoas\Configuration\Annotation; +use JMS\Serializer\Annotation\AnnotationUtilsTrait; +use Symfony\Contracts\Service\Attribute\Required; + /** * @Annotation * @Target("ANNOTATION") */ +#[\Attribute(0)] class Embedded { + use AnnotationUtilsTrait; + /** * @Required * @var mixed */ + #[Required] public $content; /** @@ -32,4 +39,9 @@ class Embedded * phpcs:enable */ public $exclusion = null; + + public function __construct($values = [], $content = null, ?string $type = null, $xmlElementName = null, $exclusion = null) + { + $this->loadAnnotationParameters(get_defined_vars()); + } } diff --git a/src/Configuration/Annotation/Exclusion.php b/src/Configuration/Annotation/Exclusion.php index 59b1cfc1..626583a6 100644 --- a/src/Configuration/Annotation/Exclusion.php +++ b/src/Configuration/Annotation/Exclusion.php @@ -4,12 +4,17 @@ namespace Hateoas\Configuration\Annotation; +use JMS\Serializer\Annotation\AnnotationUtilsTrait; + /** * @Annotation * @Target("ANNOTATION") */ +#[\Attribute(0)] final class Exclusion { + use AnnotationUtilsTrait; + /** * @var array */ @@ -38,4 +43,9 @@ final class Exclusion * @var string */ public $excludeIf = null; + + public function __construct($values = [], ?array $groups = null, ?string $sinceVersion = null, ?string $untilVersion = null, ?int $maxDepth = null, ?string $excludeIf = null) + { + $this->loadAnnotationParameters(get_defined_vars()); + } } diff --git a/src/Configuration/Annotation/Relation.php b/src/Configuration/Annotation/Relation.php index 8f8f0747..605c668a 100644 --- a/src/Configuration/Annotation/Relation.php +++ b/src/Configuration/Annotation/Relation.php @@ -4,16 +4,23 @@ namespace Hateoas\Configuration\Annotation; +use JMS\Serializer\Annotation\AnnotationUtilsTrait; +use Symfony\Contracts\Service\Attribute\Required; + /** * @Annotation * @Target("CLASS") */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] final class Relation { + use AnnotationUtilsTrait; + /** * @Required * @var string */ + #[Required] public $name; /** @@ -37,4 +44,9 @@ final class Relation * phpcs:enable */ public $exclusion = null; + + public function __construct($values = [], ?string $name = null, $href = null, $embedded = null, array $attributes = [], ?Exclusion $exclusion = null) + { + $this->loadAnnotationParameters(get_defined_vars()); + } } diff --git a/src/Configuration/Annotation/RelationProvider.php b/src/Configuration/Annotation/RelationProvider.php index 37818c74..6e473732 100644 --- a/src/Configuration/Annotation/RelationProvider.php +++ b/src/Configuration/Annotation/RelationProvider.php @@ -4,14 +4,24 @@ namespace Hateoas\Configuration\Annotation; +use JMS\Serializer\Annotation\AnnotationUtilsTrait; + /** * @Annotation * @Target("CLASS") */ +#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] class RelationProvider { + use AnnotationUtilsTrait; + /** * @var string */ public $name; + + public function __construct($values = [], ?string $name = null) + { + $this->loadAnnotationParameters(get_defined_vars()); + } } diff --git a/src/Configuration/Annotation/Route.php b/src/Configuration/Annotation/Route.php index e4e6bf04..2a62eeed 100644 --- a/src/Configuration/Annotation/Route.php +++ b/src/Configuration/Annotation/Route.php @@ -4,22 +4,30 @@ namespace Hateoas\Configuration\Annotation; +use JMS\Serializer\Annotation\AnnotationUtilsTrait; +use Symfony\Contracts\Service\Attribute\Required; + /** * @Annotation * @Target("ANNOTATION") */ +#[\Attribute(0)] class Route { + use AnnotationUtilsTrait; + /** * @Required * @var string */ + #[Required] public $name; /** * @Required * @var mixed */ + #[Required] public $parameters = []; /** @@ -31,4 +39,9 @@ class Route * @var string */ public $generator = null; + + public function __construct($values = [], ?string $name = null, $parameters = null, $absolute = false, ?string $generator = null) + { + $this->loadAnnotationParameters(get_defined_vars()); + } } diff --git a/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php new file mode 100644 index 00000000..c85cc548 --- /dev/null +++ b/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -0,0 +1,89 @@ +reader = $reader; + } + + public function getClassAnnotations(ReflectionClass $class): array + { + $attributes = $class->getAttributes(); + + return array_merge($this->reader->getClassAnnotations($class), $this->buildAnnotations($attributes)); + } + + public function getClassAnnotation(ReflectionClass $class, $annotationName): ?object + { + $attributes = $class->getAttributes($annotationName); + + return $this->reader->getClassAnnotation($class, $annotationName) ?? $this->buildAnnotation($attributes); + } + + public function getMethodAnnotations(ReflectionMethod $method): array + { + $attributes = $method->getAttributes(); + + return array_merge($this->reader->getMethodAnnotations($method), $this->buildAnnotations($attributes)); + } + + public function getMethodAnnotation(ReflectionMethod $method, $annotationName): ?object + { + $attributes = $method->getAttributes($annotationName); + + return $this->reader->getMethodAnnotation($method, $annotationName) ?? $this->buildAnnotation($attributes); + } + + public function getPropertyAnnotations(ReflectionProperty $property): array + { + $attributes = $property->getAttributes(); + + return array_merge($this->reader->getPropertyAnnotations($property), $this->buildAnnotations($attributes)); + } + + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName): ?object + { + $attributes = $property->getAttributes($annotationName); + + return $this->reader->getPropertyAnnotation($property, $annotationName) ?? $this->buildAnnotation($attributes); + } + + private function buildAnnotation(array $attributes): ?object + { + if (!isset($attributes[0])) { + return null; + } + + return $attributes[0]->newInstance(); + } + + private function buildAnnotations(array $attributes): array + { + $result = []; + foreach ($attributes as $attribute) { + if (0 === strpos($attribute->getName(), 'Hateoas\Configuration\Annotation\\')) { + $result[] = $attribute->newInstance(); + } + } + + return $result; + } +} diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php new file mode 100644 index 00000000..54523951 --- /dev/null +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php @@ -0,0 +1,238 @@ +createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionClass(User::class); + + $delegate + ->expects($this->once()) + ->method('getClassAnnotations') + ->with($refl) + ->willReturn([]) + ; + + $result = $reader->getClassAnnotations($refl); + + $this->assertCount(9, $result); + } + + public function testGetClassAnnotationsDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionClass(EmptyClass::class); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getClassAnnotations') + ->with($refl) + ->willReturn([$annotation]) + ; + + $result = $reader->getClassAnnotations($refl); + + $this->assertSame([$annotation], $result); + } + + public function testGetClassAnnotation() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionClass(User::class); + + $delegate + ->expects($this->once()) + ->method('getClassAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn(null) + ; + + $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertInstanceOf(Annotation\RelationProvider::class, $result); + } + + public function testGetClassAnnotationDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionClass(EmptyClass::class); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getClassAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn($annotation) + ; + + $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertSame($annotation, $result); + } + + public function testGetMethodAnnotations() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); + + $delegate + ->expects($this->once()) + ->method('getMethodAnnotations') + ->with($refl) + ->willReturn([]) + ; + + $result = $reader->getMethodAnnotations($refl); + + $this->assertEmpty($result); + } + + public function testGetMethodAnnotationsDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getMethodAnnotations') + ->with($refl) + ->willReturn([$annotation]) + ; + + $result = $reader->getMethodAnnotations($refl); + + $this->assertSame([$annotation], $result); + } + + public function testGetMethodAnnotation() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); + + $delegate + ->expects($this->once()) + ->method('getMethodAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn(null) + ; + + $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertEmpty($result); + } + + public function testGetMethodAnnotationDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getMethodAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn($annotation) + ; + + $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertSame($annotation, $result); + } + + public function testGetPropertyAnnotations() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); + + $delegate + ->expects($this->once()) + ->method('getPropertyAnnotations') + ->with($refl) + ->willReturn([]) + ; + + $result = $reader->getPropertyAnnotations($refl); + + $this->assertEmpty($result); + } + + public function testGetPropertyAnnotationsDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getPropertyAnnotations') + ->with($refl) + ->willReturn([$annotation]) + ; + + $result = $reader->getPropertyAnnotations($refl); + + $this->assertSame([$annotation], $result); + } + + public function testGetPropertyAnnotation() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); + + $delegate + ->expects($this->once()) + ->method('getPropertyAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn(null) + ; + + $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertEmpty($result); + } + + public function testGetPropertyAnnotationDelegated() + { + $delegate = $this->createMock(Reader::class); + $reader = new AttributeReader($delegate); + $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); + $annotation = new Annotation\RelationProvider(); + + $delegate + ->expects($this->once()) + ->method('getPropertyAnnotation') + ->with($refl, Annotation\RelationProvider::class) + ->willReturn($annotation) + ; + + $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); + + $this->assertSame($annotation, $result); + } +} diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php new file mode 100644 index 00000000..baf92cce --- /dev/null +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -0,0 +1,29 @@ +createMock(Reader::class); + $driver + ->expects($this->once()) + ->method('getClassAnnotations') + ->willReturn([]) + ; + + return new AnnotationDriver( + new AttributeReader($driver), + $this->getExpressionEvaluator(), + $this->createProvider(), + $this->createTypeParser() + ); + } +} diff --git a/tests/Hateoas/Tests/Fixtures/User.php b/tests/Hateoas/Tests/Fixtures/User.php index bfdb1236..a373c347 100644 --- a/tests/Hateoas/Tests/Fixtures/User.php +++ b/tests/Hateoas/Tests/Fixtures/User.php @@ -39,6 +39,39 @@ * @Hateoas\Relation("attribute_with_expression", href = "baz", attributes = {"baz" = "expr(object.getId())"}) * @Hateoas\RelationProvider("Hateoas\Tests\Fixtures\User::getRelations") */ +#[ + Hateoas\Relation(name: "self", href: "http://hateoas.web/user/42", attributes: ["type" => "application/json"]), + Hateoas\Relation(name: "foo", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"]), embedded: "expr(object.getFoo())"), + Hateoas\Relation(name: "bar", href: "foo", embedded: new Hateoas\Embedded(content: "data", xmlElementName: "barTag")), + Hateoas\Relation(name: "baz", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: true), embedded: "expr(object.getFoo())"), + Hateoas\Relation(name: "boom", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: false), embedded: "expr(object.getFoo())"), + Hateoas\Relation(name: "badaboom", embedded: "expr(object.getFoo())"), + Hateoas\Relation( + name: "hello", + href: "/hello", + embedded: new Hateoas\Embedded( + content: "hello", + type: "string", + xmlElementName: "barTag", + exclusion: new Hateoas\Exclusion( + groups: ["group3", "group4"], + sinceVersion: "1.1", + untilVersion: "2.3", + maxDepth: 43, + excludeIf: "bar" + ) + ), + exclusion: new Hateoas\Exclusion( + groups: ["group1", "group2"], + sinceVersion: "1", + untilVersion: "2.2", + maxDepth: 42, + excludeIf: "foo" + ) + ), + Hateoas\Relation(name: "attribute_with_expression", href: "baz", attributes: ["baz" => "expr(object.getId())"]), + Hateoas\RelationProvider(name: "Hateoas\Tests\Fixtures\User::getRelations") +] class User { /** From 4427f819b4575f2f893fbf574cb7c87dd662492f Mon Sep 17 00:00:00 2001 From: ixarlie Date: Tue, 10 Jan 2023 22:16:56 +0100 Subject: [PATCH 02/15] make User attributes compatible when running php version lower than 8.0 --- tests/Hateoas/Tests/Fixtures/User.php | 42 ++++++--------------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/tests/Hateoas/Tests/Fixtures/User.php b/tests/Hateoas/Tests/Fixtures/User.php index a373c347..cd2e2c56 100644 --- a/tests/Hateoas/Tests/Fixtures/User.php +++ b/tests/Hateoas/Tests/Fixtures/User.php @@ -39,39 +39,15 @@ * @Hateoas\Relation("attribute_with_expression", href = "baz", attributes = {"baz" = "expr(object.getId())"}) * @Hateoas\RelationProvider("Hateoas\Tests\Fixtures\User::getRelations") */ -#[ - Hateoas\Relation(name: "self", href: "http://hateoas.web/user/42", attributes: ["type" => "application/json"]), - Hateoas\Relation(name: "foo", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"]), embedded: "expr(object.getFoo())"), - Hateoas\Relation(name: "bar", href: "foo", embedded: new Hateoas\Embedded(content: "data", xmlElementName: "barTag")), - Hateoas\Relation(name: "baz", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: true), embedded: "expr(object.getFoo())"), - Hateoas\Relation(name: "boom", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: false), embedded: "expr(object.getFoo())"), - Hateoas\Relation(name: "badaboom", embedded: "expr(object.getFoo())"), - Hateoas\Relation( - name: "hello", - href: "/hello", - embedded: new Hateoas\Embedded( - content: "hello", - type: "string", - xmlElementName: "barTag", - exclusion: new Hateoas\Exclusion( - groups: ["group3", "group4"], - sinceVersion: "1.1", - untilVersion: "2.3", - maxDepth: 43, - excludeIf: "bar" - ) - ), - exclusion: new Hateoas\Exclusion( - groups: ["group1", "group2"], - sinceVersion: "1", - untilVersion: "2.2", - maxDepth: 42, - excludeIf: "foo" - ) - ), - Hateoas\Relation(name: "attribute_with_expression", href: "baz", attributes: ["baz" => "expr(object.getId())"]), - Hateoas\RelationProvider(name: "Hateoas\Tests\Fixtures\User::getRelations") -] +#[Hateoas\Relation(name: "self", href: "http://hateoas.web/user/42", attributes: ["type" => "application/json"])] +#[Hateoas\Relation(name: "foo", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"]), embedded: "expr(object.getFoo())")] +#[Hateoas\Relation(name: "bar", href: "foo", embedded: new Hateoas\Embedded(content: "data", xmlElementName: "barTag"))] +#[Hateoas\Relation(name: "baz", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: true), embedded: "expr(object.getFoo())")] +#[Hateoas\Relation(name: "boom", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: false), embedded: "expr(object.getFoo())")] +#[Hateoas\Relation(name: "badaboom", embedded: "expr(object.getFoo())")] +#[Hateoas\Relation(name: "hello", href: "/hello", embedded: new Hateoas\Embedded(content: "hello", type: "string", xmlElementName: "barTag", exclusion: new Hateoas\Exclusion(groups: ["group3", "group4"], sinceVersion: "1.1", untilVersion: "2.3", maxDepth: 43, excludeIf: "bar")), exclusion: new Hateoas\Exclusion(groups: ["group1", "group2"], sinceVersion: "1", untilVersion: "2.2", maxDepth: 42, excludeIf: "foo"))] +#[Hateoas\Relation(name: "attribute_with_expression", href: "baz", attributes: ["baz" => "expr(object.getId())"])] +#[Hateoas\RelationProvider(name: "Hateoas\Tests\Fixtures\User::getRelations")] class User { /** From 71bc139c8ea5d1bbf558c888e8f913a6a729dc83 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Tue, 10 Jan 2023 22:24:30 +0100 Subject: [PATCH 03/15] ignore attributes tests when php version is lower than 8.0 --- .../Driver/AttributeDriver/AttributeReaderTest.php | 7 +++++++ .../Configuration/Metadata/Driver/AttributeDriverTest.php | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php index 54523951..babdcc1b 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php @@ -14,6 +14,13 @@ class AttributeReaderTest extends TestCase { + public function setUp(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Attributes are available only on php 8 or higher'); + } + } + public function testGetClassAnnotations() { $delegate = $this->createMock(Reader::class); diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index baf92cce..15ada836 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -10,6 +10,13 @@ class AttributeDriverTest extends AbstractDriverTest { + public function setUp(): void + { + if (PHP_VERSION_ID < 80000) { + $this->markTestSkipped('Attributes are available only on php 8 or higher'); + } + } + public function createDriver() { $driver = $this->createMock(Reader::class); From 85df257b5ef8a42c76c99e3fff616f26712d69f0 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Tue, 10 Jan 2023 22:34:33 +0100 Subject: [PATCH 04/15] increase minimum php version to 8.1 --- .../Metadata/Driver/AttributeDriver/AttributeReaderTest.php | 4 ++-- .../Configuration/Metadata/Driver/AttributeDriverTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php index babdcc1b..bf6bd4e2 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php @@ -16,8 +16,8 @@ class AttributeReaderTest extends TestCase { public function setUp(): void { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Attributes are available only on php 8 or higher'); + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Attributes are available only on php 8.1 or higher'); } } diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index 15ada836..34c01f0d 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -12,8 +12,8 @@ class AttributeDriverTest extends AbstractDriverTest { public function setUp(): void { - if (PHP_VERSION_ID < 80000) { - $this->markTestSkipped('Attributes are available only on php 8 or higher'); + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('Attributes are available only on php 8.1 or higher'); } } From 90f6f4dae9e92ff56b85252a7589da4a2f32ba14 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Tue, 31 Jan 2023 23:34:37 +0100 Subject: [PATCH 05/15] fix coding standards issues --- src/Configuration/Annotation/Embedded.php | 6 +++- src/Configuration/Annotation/Exclusion.php | 2 +- src/Configuration/Annotation/Relation.php | 6 +++- .../Annotation/RelationProvider.php | 2 +- src/Configuration/Annotation/Route.php | 6 +++- .../AttributeDriver/AttributeReader.php | 18 ++++++++++ .../AttributeDriver/AttributeReaderTest.php | 36 +++++++------------ .../Metadata/Driver/AttributeDriverTest.php | 3 +- tests/Hateoas/Tests/Fixtures/User.php | 18 +++++----- 9 files changed, 57 insertions(+), 40 deletions(-) diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index 9acd0df7..ad322691 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -40,7 +40,11 @@ class Embedded */ public $exclusion = null; - public function __construct($values = [], $content = null, ?string $type = null, $xmlElementName = null, $exclusion = null) + /** + * @param string|array $content + * @param Exclusion|null $exclusion + */ + public function __construct(array $values = [], $content = null, ?string $type = null, ?string $xmlElementName = null, $exclusion = null) { $this->loadAnnotationParameters(get_defined_vars()); } diff --git a/src/Configuration/Annotation/Exclusion.php b/src/Configuration/Annotation/Exclusion.php index 626583a6..709bac3d 100644 --- a/src/Configuration/Annotation/Exclusion.php +++ b/src/Configuration/Annotation/Exclusion.php @@ -44,7 +44,7 @@ final class Exclusion */ public $excludeIf = null; - public function __construct($values = [], ?array $groups = null, ?string $sinceVersion = null, ?string $untilVersion = null, ?int $maxDepth = null, ?string $excludeIf = null) + public function __construct(array $values = [], ?array $groups = null, ?string $sinceVersion = null, ?string $untilVersion = null, ?int $maxDepth = null, ?string $excludeIf = null) { $this->loadAnnotationParameters(get_defined_vars()); } diff --git a/src/Configuration/Annotation/Relation.php b/src/Configuration/Annotation/Relation.php index 605c668a..ffbc640b 100644 --- a/src/Configuration/Annotation/Relation.php +++ b/src/Configuration/Annotation/Relation.php @@ -45,7 +45,11 @@ final class Relation */ public $exclusion = null; - public function __construct($values = [], ?string $name = null, $href = null, $embedded = null, array $attributes = [], ?Exclusion $exclusion = null) + /** + * @param string|Route $href + * @param string|Embedded $embedded + */ + public function __construct(array $values = [], ?string $name = null, $href = null, $embedded = null, array $attributes = [], ?Exclusion $exclusion = null) { $this->loadAnnotationParameters(get_defined_vars()); } diff --git a/src/Configuration/Annotation/RelationProvider.php b/src/Configuration/Annotation/RelationProvider.php index 6e473732..4b74dc9f 100644 --- a/src/Configuration/Annotation/RelationProvider.php +++ b/src/Configuration/Annotation/RelationProvider.php @@ -20,7 +20,7 @@ class RelationProvider */ public $name; - public function __construct($values = [], ?string $name = null) + public function __construct(array $values = [], ?string $name = null) { $this->loadAnnotationParameters(get_defined_vars()); } diff --git a/src/Configuration/Annotation/Route.php b/src/Configuration/Annotation/Route.php index 2a62eeed..5f4ba189 100644 --- a/src/Configuration/Annotation/Route.php +++ b/src/Configuration/Annotation/Route.php @@ -40,7 +40,11 @@ class Route */ public $generator = null; - public function __construct($values = [], ?string $name = null, $parameters = null, $absolute = false, ?string $generator = null) + /** + * @param array|string $parameters + * @param bool|string $absolute + */ + public function __construct(array $values = [], ?string $name = null, $parameters = null, $absolute = false, ?string $generator = null) { $this->loadAnnotationParameters(get_defined_vars()); } diff --git a/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php index c85cc548..dbf83bd5 100644 --- a/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php +++ b/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php @@ -24,6 +24,9 @@ public function __construct(Reader $reader) $this->reader = $reader; } + /** + * {@inheritDoc} + */ public function getClassAnnotations(ReflectionClass $class): array { $attributes = $class->getAttributes(); @@ -31,6 +34,9 @@ public function getClassAnnotations(ReflectionClass $class): array return array_merge($this->reader->getClassAnnotations($class), $this->buildAnnotations($attributes)); } + /** + * {@inheritDoc} + */ public function getClassAnnotation(ReflectionClass $class, $annotationName): ?object { $attributes = $class->getAttributes($annotationName); @@ -38,6 +44,9 @@ public function getClassAnnotation(ReflectionClass $class, $annotationName): ?ob return $this->reader->getClassAnnotation($class, $annotationName) ?? $this->buildAnnotation($attributes); } + /** + * {@inheritDoc} + */ public function getMethodAnnotations(ReflectionMethod $method): array { $attributes = $method->getAttributes(); @@ -45,6 +54,9 @@ public function getMethodAnnotations(ReflectionMethod $method): array return array_merge($this->reader->getMethodAnnotations($method), $this->buildAnnotations($attributes)); } + /** + * {@inheritDoc} + */ public function getMethodAnnotation(ReflectionMethod $method, $annotationName): ?object { $attributes = $method->getAttributes($annotationName); @@ -52,6 +64,9 @@ public function getMethodAnnotation(ReflectionMethod $method, $annotationName): return $this->reader->getMethodAnnotation($method, $annotationName) ?? $this->buildAnnotation($attributes); } + /** + * {@inheritDoc} + */ public function getPropertyAnnotations(ReflectionProperty $property): array { $attributes = $property->getAttributes(); @@ -59,6 +74,9 @@ public function getPropertyAnnotations(ReflectionProperty $property): array return array_merge($this->reader->getPropertyAnnotations($property), $this->buildAnnotations($attributes)); } + /** + * {@inheritDoc} + */ public function getPropertyAnnotation(ReflectionProperty $property, $annotationName): ?object { $attributes = $property->getAttributes($annotationName); diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php index bf6bd4e2..b1663441 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php @@ -31,8 +31,7 @@ public function testGetClassAnnotations() ->expects($this->once()) ->method('getClassAnnotations') ->with($refl) - ->willReturn([]) - ; + ->willReturn([]); $result = $reader->getClassAnnotations($refl); @@ -50,8 +49,7 @@ public function testGetClassAnnotationsDelegated() ->expects($this->once()) ->method('getClassAnnotations') ->with($refl) - ->willReturn([$annotation]) - ; + ->willReturn([$annotation]); $result = $reader->getClassAnnotations($refl); @@ -68,8 +66,7 @@ public function testGetClassAnnotation() ->expects($this->once()) ->method('getClassAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null) - ; + ->willReturn(null); $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); @@ -87,8 +84,7 @@ public function testGetClassAnnotationDelegated() ->expects($this->once()) ->method('getClassAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation) - ; + ->willReturn($annotation); $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); @@ -105,8 +101,7 @@ public function testGetMethodAnnotations() ->expects($this->once()) ->method('getMethodAnnotations') ->with($refl) - ->willReturn([]) - ; + ->willReturn([]); $result = $reader->getMethodAnnotations($refl); @@ -124,8 +119,7 @@ public function testGetMethodAnnotationsDelegated() ->expects($this->once()) ->method('getMethodAnnotations') ->with($refl) - ->willReturn([$annotation]) - ; + ->willReturn([$annotation]); $result = $reader->getMethodAnnotations($refl); @@ -142,8 +136,7 @@ public function testGetMethodAnnotation() ->expects($this->once()) ->method('getMethodAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null) - ; + ->willReturn(null); $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); @@ -161,8 +154,7 @@ public function testGetMethodAnnotationDelegated() ->expects($this->once()) ->method('getMethodAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation) - ; + ->willReturn($annotation); $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); @@ -179,8 +171,7 @@ public function testGetPropertyAnnotations() ->expects($this->once()) ->method('getPropertyAnnotations') ->with($refl) - ->willReturn([]) - ; + ->willReturn([]); $result = $reader->getPropertyAnnotations($refl); @@ -198,8 +189,7 @@ public function testGetPropertyAnnotationsDelegated() ->expects($this->once()) ->method('getPropertyAnnotations') ->with($refl) - ->willReturn([$annotation]) - ; + ->willReturn([$annotation]); $result = $reader->getPropertyAnnotations($refl); @@ -216,8 +206,7 @@ public function testGetPropertyAnnotation() ->expects($this->once()) ->method('getPropertyAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null) - ; + ->willReturn(null); $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); @@ -235,8 +224,7 @@ public function testGetPropertyAnnotationDelegated() ->expects($this->once()) ->method('getPropertyAnnotation') ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation) - ; + ->willReturn($annotation); $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index 34c01f0d..a3946dc3 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -23,8 +23,7 @@ public function createDriver() $driver ->expects($this->once()) ->method('getClassAnnotations') - ->willReturn([]) - ; + ->willReturn([]); return new AnnotationDriver( new AttributeReader($driver), diff --git a/tests/Hateoas/Tests/Fixtures/User.php b/tests/Hateoas/Tests/Fixtures/User.php index cd2e2c56..8c0b677b 100644 --- a/tests/Hateoas/Tests/Fixtures/User.php +++ b/tests/Hateoas/Tests/Fixtures/User.php @@ -39,15 +39,15 @@ * @Hateoas\Relation("attribute_with_expression", href = "baz", attributes = {"baz" = "expr(object.getId())"}) * @Hateoas\RelationProvider("Hateoas\Tests\Fixtures\User::getRelations") */ -#[Hateoas\Relation(name: "self", href: "http://hateoas.web/user/42", attributes: ["type" => "application/json"])] -#[Hateoas\Relation(name: "foo", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"]), embedded: "expr(object.getFoo())")] -#[Hateoas\Relation(name: "bar", href: "foo", embedded: new Hateoas\Embedded(content: "data", xmlElementName: "barTag"))] -#[Hateoas\Relation(name: "baz", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: true), embedded: "expr(object.getFoo())")] -#[Hateoas\Relation(name: "boom", href: new Hateoas\Route(name: "user_get", parameters: ["id" => "expr(object.getId())"], absolute: false), embedded: "expr(object.getFoo())")] -#[Hateoas\Relation(name: "badaboom", embedded: "expr(object.getFoo())")] -#[Hateoas\Relation(name: "hello", href: "/hello", embedded: new Hateoas\Embedded(content: "hello", type: "string", xmlElementName: "barTag", exclusion: new Hateoas\Exclusion(groups: ["group3", "group4"], sinceVersion: "1.1", untilVersion: "2.3", maxDepth: 43, excludeIf: "bar")), exclusion: new Hateoas\Exclusion(groups: ["group1", "group2"], sinceVersion: "1", untilVersion: "2.2", maxDepth: 42, excludeIf: "foo"))] -#[Hateoas\Relation(name: "attribute_with_expression", href: "baz", attributes: ["baz" => "expr(object.getId())"])] -#[Hateoas\RelationProvider(name: "Hateoas\Tests\Fixtures\User::getRelations")] +#[Hateoas\Relation(name: 'self', href: 'http://hateoas.web/user/42', attributes: ['type' => 'application/json'])] +#[Hateoas\Relation(name: 'foo', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())']), embedded: 'expr(object.getFoo())')] +#[Hateoas\Relation(name: 'bar', href: 'foo', embedded: new Hateoas\Embedded(content: 'data', xmlElementName: 'barTag'))] +#[Hateoas\Relation(name: 'baz', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: true), embedded: 'expr(object.getFoo())')] +#[Hateoas\Relation(name: 'boom', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: false), embedded: 'expr(object.getFoo())')] +#[Hateoas\Relation(name: 'badaboom', embedded: 'expr(object.getFoo())')] +#[Hateoas\Relation(name: 'hello', href: '/hello', embedded: new Hateoas\Embedded(content: 'hello', type: 'string', xmlElementName: 'barTag', exclusion: new Hateoas\Exclusion(groups: ['group3', 'group4'], sinceVersion: '1.1', untilVersion: '2.3', maxDepth: 43, excludeIf: 'bar')), exclusion: new Hateoas\Exclusion(groups: ['group1', 'group2'], sinceVersion: '1', untilVersion: '2.2', maxDepth: 42, excludeIf: 'foo'))] +#[Hateoas\Relation(name: 'attribute_with_expression', href: 'baz', attributes: ['baz' => 'expr(object.getId())'])] +#[Hateoas\RelationProvider(name: 'Hateoas\Tests\Fixtures\User::getRelations')] class User { /** From c8fbfe6075eee343890e0bf63beca27dfad85b77 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Wed, 1 Feb 2023 00:33:44 +0100 Subject: [PATCH 06/15] fix tests. use new user class for php attributes --- .../Metadata/Driver/AbstractDriverTest.php | 7 ++- .../Metadata/Driver/AttributeDriverTest.php | 9 +++- tests/Hateoas/Tests/Fixtures/User.php | 9 ---- .../Tests/Fixtures/UserPhpAttributes.php | 53 +++++++++++++++++++ 4 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AbstractDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AbstractDriverTest.php index 0e5abfe7..51f14a0f 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AbstractDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AbstractDriverTest.php @@ -41,6 +41,11 @@ protected function createTypeParser(): ParserInterface return new Parser(); } + protected function getUserClass(): string + { + return 'Hateoas\Tests\Fixtures\User'; + } + /** * @return DriverInterface */ @@ -49,7 +54,7 @@ abstract public function createDriver(); public function testUser() { $driver = $this->createDriver(); - $class = new \ReflectionClass('Hateoas\Tests\Fixtures\User'); + $class = new \ReflectionClass($this->getUserClass()); $classMetadata = $driver->loadMetadataForClass($class); $exp = $this->getExpressionEvaluator(); diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index a3946dc3..a9cd69cf 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -10,11 +10,18 @@ class AttributeDriverTest extends AbstractDriverTest { - public function setUp(): void + protected function getUserClass(): string + { + return 'Hateoas\Tests\Fixtures\UserPhpAttributes'; + } + + public function testUser() { if (PHP_VERSION_ID < 80100) { $this->markTestSkipped('Attributes are available only on php 8.1 or higher'); } + + parent::testUser(); } public function createDriver() diff --git a/tests/Hateoas/Tests/Fixtures/User.php b/tests/Hateoas/Tests/Fixtures/User.php index 8c0b677b..bfdb1236 100644 --- a/tests/Hateoas/Tests/Fixtures/User.php +++ b/tests/Hateoas/Tests/Fixtures/User.php @@ -39,15 +39,6 @@ * @Hateoas\Relation("attribute_with_expression", href = "baz", attributes = {"baz" = "expr(object.getId())"}) * @Hateoas\RelationProvider("Hateoas\Tests\Fixtures\User::getRelations") */ -#[Hateoas\Relation(name: 'self', href: 'http://hateoas.web/user/42', attributes: ['type' => 'application/json'])] -#[Hateoas\Relation(name: 'foo', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())']), embedded: 'expr(object.getFoo())')] -#[Hateoas\Relation(name: 'bar', href: 'foo', embedded: new Hateoas\Embedded(content: 'data', xmlElementName: 'barTag'))] -#[Hateoas\Relation(name: 'baz', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: true), embedded: 'expr(object.getFoo())')] -#[Hateoas\Relation(name: 'boom', href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: false), embedded: 'expr(object.getFoo())')] -#[Hateoas\Relation(name: 'badaboom', embedded: 'expr(object.getFoo())')] -#[Hateoas\Relation(name: 'hello', href: '/hello', embedded: new Hateoas\Embedded(content: 'hello', type: 'string', xmlElementName: 'barTag', exclusion: new Hateoas\Exclusion(groups: ['group3', 'group4'], sinceVersion: '1.1', untilVersion: '2.3', maxDepth: 43, excludeIf: 'bar')), exclusion: new Hateoas\Exclusion(groups: ['group1', 'group2'], sinceVersion: '1', untilVersion: '2.2', maxDepth: 42, excludeIf: 'foo'))] -#[Hateoas\Relation(name: 'attribute_with_expression', href: 'baz', attributes: ['baz' => 'expr(object.getId())'])] -#[Hateoas\RelationProvider(name: 'Hateoas\Tests\Fixtures\User::getRelations')] class User { /** diff --git a/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php b/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php new file mode 100644 index 00000000..05cf1286 --- /dev/null +++ b/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php @@ -0,0 +1,53 @@ + 'application/json'])] +#[Hateoas\Relation( + name: 'foo', + href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())']), + embedded: 'expr(object.getFoo())' +)] +#[Hateoas\Relation(name: 'bar', href: 'foo', embedded: new Hateoas\Embedded(content: 'data', xmlElementName: 'barTag'))] +#[Hateoas\Relation( + name: 'baz', + href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: true), + embedded: 'expr(object.getFoo())' +)] +#[Hateoas\Relation( + name: 'boom', + href: new Hateoas\Route(name: 'user_get', parameters: ['id' => 'expr(object.getId())'], absolute: false), + embedded: 'expr(object.getFoo())' +)] +#[Hateoas\Relation(name: 'badaboom', embedded: 'expr(object.getFoo())')] +#[Hateoas\Relation( + name: 'hello', + href: '/hello', + embedded: new Hateoas\Embedded( + content: 'hello', + type: 'string', + xmlElementName: 'barTag', + exclusion: new Hateoas\Exclusion( + groups: ['group3', 'group4'], + sinceVersion: '1.1', + untilVersion: '2.3', + maxDepth: 43, + excludeIf: 'bar') + ), + exclusion: new Hateoas\Exclusion( + groups: ['group1', 'group2'], + sinceVersion: '1', + untilVersion: '2.2', + maxDepth: 42, + excludeIf: 'foo' + ) +)] +#[Hateoas\Relation(name: 'attribute_with_expression', href: 'baz', attributes: ['baz' => 'expr(object.getId())'])] +#[Hateoas\RelationProvider(name: 'Hateoas\Tests\Fixtures\User::getRelations')] +class UserPhpAttributes +{ +} From 6aeb4e41a698afc9fc2fbdab63b31d4ebd621e02 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:17:52 +0100 Subject: [PATCH 07/15] remove Required attribute --- src/Configuration/Annotation/Embedded.php | 2 -- src/Configuration/Annotation/Relation.php | 2 -- src/Configuration/Annotation/Route.php | 3 --- 3 files changed, 7 deletions(-) diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index ad322691..0dbdd8d2 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -5,7 +5,6 @@ namespace Hateoas\Configuration\Annotation; use JMS\Serializer\Annotation\AnnotationUtilsTrait; -use Symfony\Contracts\Service\Attribute\Required; /** * @Annotation @@ -20,7 +19,6 @@ class Embedded * @Required * @var mixed */ - #[Required] public $content; /** diff --git a/src/Configuration/Annotation/Relation.php b/src/Configuration/Annotation/Relation.php index ffbc640b..398bce3a 100644 --- a/src/Configuration/Annotation/Relation.php +++ b/src/Configuration/Annotation/Relation.php @@ -5,7 +5,6 @@ namespace Hateoas\Configuration\Annotation; use JMS\Serializer\Annotation\AnnotationUtilsTrait; -use Symfony\Contracts\Service\Attribute\Required; /** * @Annotation @@ -20,7 +19,6 @@ final class Relation * @Required * @var string */ - #[Required] public $name; /** diff --git a/src/Configuration/Annotation/Route.php b/src/Configuration/Annotation/Route.php index 5f4ba189..e3e3965c 100644 --- a/src/Configuration/Annotation/Route.php +++ b/src/Configuration/Annotation/Route.php @@ -5,7 +5,6 @@ namespace Hateoas\Configuration\Annotation; use JMS\Serializer\Annotation\AnnotationUtilsTrait; -use Symfony\Contracts\Service\Attribute\Required; /** * @Annotation @@ -20,14 +19,12 @@ class Route * @Required * @var string */ - #[Required] public $name; /** * @Required * @var mixed */ - #[Required] public $parameters = []; /** From 2ba81d8d20182d9e6930678863e658ca87baaed6 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:22:21 +0100 Subject: [PATCH 08/15] typehint exclusion Embedded constructor --- src/Configuration/Annotation/Embedded.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index 0dbdd8d2..76d4d9df 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -42,7 +42,7 @@ class Embedded * @param string|array $content * @param Exclusion|null $exclusion */ - public function __construct(array $values = [], $content = null, ?string $type = null, ?string $xmlElementName = null, $exclusion = null) + public function __construct(array $values = [], $content = null, ?string $type = null, ?string $xmlElementName = null, ?Exclusion $exclusion = null) { $this->loadAnnotationParameters(get_defined_vars()); } From e45c60a4e7f790bfaed0b619f364467af612c824 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:52:56 +0100 Subject: [PATCH 09/15] decoupling annotation and attribute drivers --- .phpunit.result.cache | 1 + .../Metadata/Driver/AnnotationDriver.php | 127 +--------- .../Driver/AnnotationOrAttributeDriver.php | 146 +++++++++++ .../Metadata/Driver/AttributeDriver.php | 19 ++ .../AttributeDriver/AttributeReader.php | 107 -------- .../AttributeDriver/AttributeReaderTest.php | 233 ------------------ .../Metadata/Driver/AttributeDriverTest.php | 33 +-- 7 files changed, 181 insertions(+), 485 deletions(-) create mode 100644 .phpunit.result.cache create mode 100644 src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php create mode 100644 src/Configuration/Metadata/Driver/AttributeDriver.php delete mode 100644 src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php delete mode 100644 tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php diff --git a/.phpunit.result.cache b/.phpunit.result.cache new file mode 100644 index 00000000..19879a20 --- /dev/null +++ b/.phpunit.result.cache @@ -0,0 +1 @@ +{"version":1,"defects":[],"times":{"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AttributeDriverTest::testUser":0.03,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AttributeDriverTest::testEmptyClass":0.001,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AnnotationDriverTest::testUser":0.048,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AnnotationDriverTest::testEmptyClass":0.001}} \ No newline at end of file diff --git a/src/Configuration/Metadata/Driver/AnnotationDriver.php b/src/Configuration/Metadata/Driver/AnnotationDriver.php index 1f6b8fad..214c9cb8 100644 --- a/src/Configuration/Metadata/Driver/AnnotationDriver.php +++ b/src/Configuration/Metadata/Driver/AnnotationDriver.php @@ -5,147 +5,34 @@ namespace Hateoas\Configuration\Metadata\Driver; use Doctrine\Common\Annotations\Reader as AnnotationsReader; -use Hateoas\Configuration\Annotation; -use Hateoas\Configuration\Embedded; -use Hateoas\Configuration\Exclusion; -use Hateoas\Configuration\Metadata\ClassMetadata; + use Hateoas\Configuration\Provider\RelationProviderInterface; -use Hateoas\Configuration\Relation; -use Hateoas\Configuration\RelationProvider; -use Hateoas\Configuration\Route; use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface; -use JMS\Serializer\Expression\Expression; use JMS\Serializer\Type\ParserInterface; -use Metadata\ClassMetadata as JMSClassMetadata; -use Metadata\Driver\DriverInterface; -class AnnotationDriver implements DriverInterface +class AnnotationDriver extends AnnotationOrAttributeDriver { - use CheckExpressionTrait; - /** * @var AnnotationsReader */ private $reader; - /** - * @var RelationProviderInterface - */ - private $relationProvider; - - /** - * @var ParserInterface - */ - private $typeParser; - public function __construct( AnnotationsReader $reader, CompilableExpressionEvaluatorInterface $expressionLanguage, RelationProviderInterface $relationProvider, ParserInterface $typeParser ) { - $this->reader = $reader; - $this->relationProvider = $relationProvider; - $this->expressionLanguage = $expressionLanguage; - $this->typeParser = $typeParser; - } - - public function loadMetadataForClass(\ReflectionClass $class): ?JMSClassMetadata - { - $annotations = $this->reader->getClassAnnotations($class); - - if (0 === count($annotations)) { - return null; - } + parent::__construct($expressionLanguage, $relationProvider, $typeParser); - $classMetadata = new ClassMetadata($class->getName()); - $classMetadata->fileResources[] = $class->getFilename(); - - foreach ($annotations as $annotation) { - if ($annotation instanceof Annotation\Relation) { - $classMetadata->addRelation(new Relation( - $annotation->name, - $this->createHref($annotation->href), - $this->createEmbedded($annotation->embedded), - $this->checkExpressionArray($annotation->attributes) ?: [], - $this->createExclusion($annotation->exclusion) - )); - } elseif ($annotation instanceof Annotation\RelationProvider) { - $relations = $this->relationProvider->getRelations(new RelationProvider($annotation->name), $class->getName()); - foreach ($relations as $relation) { - $classMetadata->addRelation($relation); - } - } - } - - if (0 === count($classMetadata->getRelations())) { - return null; - } - - return $classMetadata; - } - - private function parseExclusion(Annotation\Exclusion $exclusion): Exclusion - { - return new Exclusion( - $exclusion->groups, - null !== $exclusion->sinceVersion ? (string) $exclusion->sinceVersion : null, - null !== $exclusion->untilVersion ? (string) $exclusion->untilVersion : null, - null !== $exclusion->maxDepth ? (int) $exclusion->maxDepth : null, - $this->checkExpression($exclusion->excludeIf) - ); - } - - /** - * @param mixed $href - * - * @return Expression|mixed - */ - private function createHref($href) - { - if ($href instanceof Annotation\Route) { - return new Route( - $this->checkExpression($href->name), - is_array($href->parameters) ? $this->checkExpressionArray($href->parameters) : $this->checkExpression($href->parameters), - $this->checkExpression($href->absolute), - $href->generator - ); - } - - return $this->checkExpression($href); + $this->reader = $reader; } /** - * @param Annotation\Embedded|mixed $embedded - * - * @return Expression|mixed + * {@inheritdoc} */ - private function createEmbedded($embedded) - { - if ($embedded instanceof Annotation\Embedded) { - $embeddedExclusion = $embedded->exclusion; - - if (null !== $embeddedExclusion) { - $embeddedExclusion = $this->parseExclusion($embeddedExclusion); - } - - return new Embedded( - $this->checkExpression($embedded->content), - $this->checkExpression($embedded->xmlElementName), - $embeddedExclusion, - null !== $embedded->type ? $this->typeParser->parse($embedded->type) : null - ); - } - - return $this->checkExpression($embedded); - } - - private function createExclusion(?Annotation\Exclusion $exclusion = null): ?Exclusion + protected function getClassAnnotations(\ReflectionClass $class): array { - if (null !== $exclusion) { - $exclusion = $this->parseExclusion($exclusion); - } - - return $exclusion; + return $this->reader->getClassAnnotations($class); } } diff --git a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php new file mode 100644 index 00000000..72d853d8 --- /dev/null +++ b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -0,0 +1,146 @@ +relationProvider = $relationProvider; + $this->expressionLanguage = $expressionLanguage; + $this->typeParser = $typeParser; + } + + public function loadMetadataForClass(\ReflectionClass $class): ?JMSClassMetadata + { + $annotations = $this->getClassAnnotations($class); + + if (0 === count($annotations)) { + return null; + } + + $classMetadata = new ClassMetadata($class->getName()); + $classMetadata->fileResources[] = $class->getFilename(); + + foreach ($annotations as $annotation) { + if ($annotation instanceof Annotation\Relation) { + $classMetadata->addRelation(new Relation( + $annotation->name, + $this->createHref($annotation->href), + $this->createEmbedded($annotation->embedded), + $this->checkExpressionArray($annotation->attributes) ?: [], + $this->createExclusion($annotation->exclusion) + )); + } elseif ($annotation instanceof Annotation\RelationProvider) { + $relations = $this->relationProvider->getRelations(new RelationProvider($annotation->name), $class->getName()); + foreach ($relations as $relation) { + $classMetadata->addRelation($relation); + } + } + } + + if (0 === count($classMetadata->getRelations())) { + return null; + } + + return $classMetadata; + } + + /** + * @return array + */ + abstract protected function getClassAnnotations(\ReflectionClass $class): array; + + private function parseExclusion(Annotation\Exclusion $exclusion): Exclusion + { + return new Exclusion( + $exclusion->groups, + null !== $exclusion->sinceVersion ? (string)$exclusion->sinceVersion : null, + null !== $exclusion->untilVersion ? (string)$exclusion->untilVersion : null, + null !== $exclusion->maxDepth ? (int)$exclusion->maxDepth : null, + $this->checkExpression($exclusion->excludeIf) + ); + } + + /** + * @param mixed $href + * + * @return Expression|mixed + */ + private function createHref($href) + { + if ($href instanceof Annotation\Route) { + return new Route( + $this->checkExpression($href->name), + is_array($href->parameters) ? $this->checkExpressionArray($href->parameters) : $this->checkExpression($href->parameters), + $this->checkExpression($href->absolute), + $href->generator + ); + } + + return $this->checkExpression($href); + } + + /** + * @param Annotation\Embedded|mixed $embedded + * + * @return Expression|mixed + */ + private function createEmbedded($embedded) + { + if ($embedded instanceof Annotation\Embedded) { + $embeddedExclusion = $embedded->exclusion; + + if (null !== $embeddedExclusion) { + $embeddedExclusion = $this->parseExclusion($embeddedExclusion); + } + + return new Embedded( + $this->checkExpression($embedded->content), + $this->checkExpression($embedded->xmlElementName), + $embeddedExclusion, + null !== $embedded->type ? $this->typeParser->parse($embedded->type) : null + ); + } + + return $this->checkExpression($embedded); + } + + private function createExclusion(?Annotation\Exclusion $exclusion = null): ?Exclusion + { + if (null !== $exclusion) { + $exclusion = $this->parseExclusion($exclusion); + } + + return $exclusion; + } +} \ No newline at end of file diff --git a/src/Configuration/Metadata/Driver/AttributeDriver.php b/src/Configuration/Metadata/Driver/AttributeDriver.php new file mode 100644 index 00000000..0c40509d --- /dev/null +++ b/src/Configuration/Metadata/Driver/AttributeDriver.php @@ -0,0 +1,19 @@ +newInstance(); + }, + $class->getAttributes() + ); + } +} \ No newline at end of file diff --git a/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php b/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php deleted file mode 100644 index dbf83bd5..00000000 --- a/src/Configuration/Metadata/Driver/AttributeDriver/AttributeReader.php +++ /dev/null @@ -1,107 +0,0 @@ -reader = $reader; - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotations(ReflectionClass $class): array - { - $attributes = $class->getAttributes(); - - return array_merge($this->reader->getClassAnnotations($class), $this->buildAnnotations($attributes)); - } - - /** - * {@inheritDoc} - */ - public function getClassAnnotation(ReflectionClass $class, $annotationName): ?object - { - $attributes = $class->getAttributes($annotationName); - - return $this->reader->getClassAnnotation($class, $annotationName) ?? $this->buildAnnotation($attributes); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotations(ReflectionMethod $method): array - { - $attributes = $method->getAttributes(); - - return array_merge($this->reader->getMethodAnnotations($method), $this->buildAnnotations($attributes)); - } - - /** - * {@inheritDoc} - */ - public function getMethodAnnotation(ReflectionMethod $method, $annotationName): ?object - { - $attributes = $method->getAttributes($annotationName); - - return $this->reader->getMethodAnnotation($method, $annotationName) ?? $this->buildAnnotation($attributes); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotations(ReflectionProperty $property): array - { - $attributes = $property->getAttributes(); - - return array_merge($this->reader->getPropertyAnnotations($property), $this->buildAnnotations($attributes)); - } - - /** - * {@inheritDoc} - */ - public function getPropertyAnnotation(ReflectionProperty $property, $annotationName): ?object - { - $attributes = $property->getAttributes($annotationName); - - return $this->reader->getPropertyAnnotation($property, $annotationName) ?? $this->buildAnnotation($attributes); - } - - private function buildAnnotation(array $attributes): ?object - { - if (!isset($attributes[0])) { - return null; - } - - return $attributes[0]->newInstance(); - } - - private function buildAnnotations(array $attributes): array - { - $result = []; - foreach ($attributes as $attribute) { - if (0 === strpos($attribute->getName(), 'Hateoas\Configuration\Annotation\\')) { - $result[] = $attribute->newInstance(); - } - } - - return $result; - } -} diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php deleted file mode 100644 index b1663441..00000000 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriver/AttributeReaderTest.php +++ /dev/null @@ -1,233 +0,0 @@ -markTestSkipped('Attributes are available only on php 8.1 or higher'); - } - } - - public function testGetClassAnnotations() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionClass(User::class); - - $delegate - ->expects($this->once()) - ->method('getClassAnnotations') - ->with($refl) - ->willReturn([]); - - $result = $reader->getClassAnnotations($refl); - - $this->assertCount(9, $result); - } - - public function testGetClassAnnotationsDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionClass(EmptyClass::class); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getClassAnnotations') - ->with($refl) - ->willReturn([$annotation]); - - $result = $reader->getClassAnnotations($refl); - - $this->assertSame([$annotation], $result); - } - - public function testGetClassAnnotation() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionClass(User::class); - - $delegate - ->expects($this->once()) - ->method('getClassAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null); - - $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertInstanceOf(Annotation\RelationProvider::class, $result); - } - - public function testGetClassAnnotationDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionClass(EmptyClass::class); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getClassAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation); - - $result = $reader->getClassAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertSame($annotation, $result); - } - - public function testGetMethodAnnotations() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); - - $delegate - ->expects($this->once()) - ->method('getMethodAnnotations') - ->with($refl) - ->willReturn([]); - - $result = $reader->getMethodAnnotations($refl); - - $this->assertEmpty($result); - } - - public function testGetMethodAnnotationsDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getMethodAnnotations') - ->with($refl) - ->willReturn([$annotation]); - - $result = $reader->getMethodAnnotations($refl); - - $this->assertSame([$annotation], $result); - } - - public function testGetMethodAnnotation() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); - - $delegate - ->expects($this->once()) - ->method('getMethodAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null); - - $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertEmpty($result); - } - - public function testGetMethodAnnotationDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionMethod(NoAnnotations::class, 'id'); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getMethodAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation); - - $result = $reader->getMethodAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertSame($annotation, $result); - } - - public function testGetPropertyAnnotations() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); - - $delegate - ->expects($this->once()) - ->method('getPropertyAnnotations') - ->with($refl) - ->willReturn([]); - - $result = $reader->getPropertyAnnotations($refl); - - $this->assertEmpty($result); - } - - public function testGetPropertyAnnotationsDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getPropertyAnnotations') - ->with($refl) - ->willReturn([$annotation]); - - $result = $reader->getPropertyAnnotations($refl); - - $this->assertSame([$annotation], $result); - } - - public function testGetPropertyAnnotation() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); - - $delegate - ->expects($this->once()) - ->method('getPropertyAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn(null); - - $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertEmpty($result); - } - - public function testGetPropertyAnnotationDelegated() - { - $delegate = $this->createMock(Reader::class); - $reader = new AttributeReader($delegate); - $refl = new \ReflectionProperty(NoAnnotations::class, 'id'); - $annotation = new Annotation\RelationProvider(); - - $delegate - ->expects($this->once()) - ->method('getPropertyAnnotation') - ->with($refl, Annotation\RelationProvider::class) - ->willReturn($annotation); - - $result = $reader->getPropertyAnnotation($refl, Annotation\RelationProvider::class); - - $this->assertSame($annotation, $result); - } -} diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index a9cd69cf..46d559e3 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -4,39 +4,22 @@ namespace Hateoas\Tests\Configuration\Metadata\Driver; -use Doctrine\Common\Annotations\Reader; -use Hateoas\Configuration\Metadata\Driver\AnnotationDriver; -use Hateoas\Configuration\Metadata\Driver\AttributeDriver\AttributeReader; +use Hateoas\Configuration\Metadata\Driver\AttributeDriver; +use Hateoas\Tests\Fixtures\UserPhpAttributes; class AttributeDriverTest extends AbstractDriverTest { - protected function getUserClass(): string - { - return 'Hateoas\Tests\Fixtures\UserPhpAttributes'; - } - - public function testUser() - { - if (PHP_VERSION_ID < 80100) { - $this->markTestSkipped('Attributes are available only on php 8.1 or higher'); - } - - parent::testUser(); - } - public function createDriver() { - $driver = $this->createMock(Reader::class); - $driver - ->expects($this->once()) - ->method('getClassAnnotations') - ->willReturn([]); - - return new AnnotationDriver( - new AttributeReader($driver), + return new AttributeDriver( $this->getExpressionEvaluator(), $this->createProvider(), $this->createTypeParser() ); } + + protected function getUserClass(): string + { + return UserPhpAttributes::class; + } } From 68713d31d08c14768d4d6256fefa9ab3512906bb Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:53:40 +0100 Subject: [PATCH 10/15] remove attributes 0 target value --- src/Configuration/Annotation/Embedded.php | 2 +- src/Configuration/Annotation/Exclusion.php | 2 +- src/Configuration/Annotation/Route.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index 76d4d9df..cf0df657 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -10,7 +10,7 @@ * @Annotation * @Target("ANNOTATION") */ -#[\Attribute(0)] +#[\Attribute] class Embedded { use AnnotationUtilsTrait; diff --git a/src/Configuration/Annotation/Exclusion.php b/src/Configuration/Annotation/Exclusion.php index 709bac3d..27061ab6 100644 --- a/src/Configuration/Annotation/Exclusion.php +++ b/src/Configuration/Annotation/Exclusion.php @@ -10,7 +10,7 @@ * @Annotation * @Target("ANNOTATION") */ -#[\Attribute(0)] +#[\Attribute] final class Exclusion { use AnnotationUtilsTrait; diff --git a/src/Configuration/Annotation/Route.php b/src/Configuration/Annotation/Route.php index e3e3965c..629fc758 100644 --- a/src/Configuration/Annotation/Route.php +++ b/src/Configuration/Annotation/Route.php @@ -10,7 +10,7 @@ * @Annotation * @Target("ANNOTATION") */ -#[\Attribute(0)] +#[\Attribute] class Route { use AnnotationUtilsTrait; From 384c4e4d26ca469af2d1bb572952d386c6b4637f Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:54:48 +0100 Subject: [PATCH 11/15] remove phpunit result cache file --- .phpunit.result.cache | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .phpunit.result.cache diff --git a/.phpunit.result.cache b/.phpunit.result.cache deleted file mode 100644 index 19879a20..00000000 --- a/.phpunit.result.cache +++ /dev/null @@ -1 +0,0 @@ -{"version":1,"defects":[],"times":{"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AttributeDriverTest::testUser":0.03,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AttributeDriverTest::testEmptyClass":0.001,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AnnotationDriverTest::testUser":0.048,"Hateoas\\Tests\\Configuration\\Metadata\\Driver\\AnnotationDriverTest::testEmptyClass":0.001}} \ No newline at end of file From 374e24b8d1fd1dea3fd725a49e896a3dc254fafd Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:56:53 +0100 Subject: [PATCH 12/15] fix missing eol --- .../Metadata/Driver/AnnotationOrAttributeDriver.php | 2 +- src/Configuration/Metadata/Driver/AttributeDriver.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php index 72d853d8..6b25852d 100644 --- a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -143,4 +143,4 @@ private function createExclusion(?Annotation\Exclusion $exclusion = null): ?Excl return $exclusion; } -} \ No newline at end of file +} diff --git a/src/Configuration/Metadata/Driver/AttributeDriver.php b/src/Configuration/Metadata/Driver/AttributeDriver.php index 0c40509d..d4258ac7 100644 --- a/src/Configuration/Metadata/Driver/AttributeDriver.php +++ b/src/Configuration/Metadata/Driver/AttributeDriver.php @@ -16,4 +16,4 @@ static function (\ReflectionAttribute $attribute): object { $class->getAttributes() ); } -} \ No newline at end of file +} From be9da1b169a3999831d8b4fe122393eac5f989f5 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Fri, 12 Jan 2024 00:57:41 +0100 Subject: [PATCH 13/15] add missing declare strict types --- .../Metadata/Driver/AnnotationOrAttributeDriver.php | 2 ++ src/Configuration/Metadata/Driver/AttributeDriver.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php index 6b25852d..dde9a7d6 100644 --- a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -1,5 +1,7 @@ Date: Fri, 12 Jan 2024 01:02:52 +0100 Subject: [PATCH 14/15] fix phpcs --- src/Configuration/Annotation/Embedded.php | 1 - src/Configuration/Metadata/Driver/AnnotationDriver.php | 1 - .../Metadata/Driver/AnnotationOrAttributeDriver.php | 6 +++--- tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php | 3 ++- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Configuration/Annotation/Embedded.php b/src/Configuration/Annotation/Embedded.php index cf0df657..25dd394d 100644 --- a/src/Configuration/Annotation/Embedded.php +++ b/src/Configuration/Annotation/Embedded.php @@ -40,7 +40,6 @@ class Embedded /** * @param string|array $content - * @param Exclusion|null $exclusion */ public function __construct(array $values = [], $content = null, ?string $type = null, ?string $xmlElementName = null, ?Exclusion $exclusion = null) { diff --git a/src/Configuration/Metadata/Driver/AnnotationDriver.php b/src/Configuration/Metadata/Driver/AnnotationDriver.php index 214c9cb8..8e2c5c58 100644 --- a/src/Configuration/Metadata/Driver/AnnotationDriver.php +++ b/src/Configuration/Metadata/Driver/AnnotationDriver.php @@ -5,7 +5,6 @@ namespace Hateoas\Configuration\Metadata\Driver; use Doctrine\Common\Annotations\Reader as AnnotationsReader; - use Hateoas\Configuration\Provider\RelationProviderInterface; use JMS\Serializer\Expression\CompilableExpressionEvaluatorInterface; use JMS\Serializer\Type\ParserInterface; diff --git a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php index dde9a7d6..d94bf666 100644 --- a/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php +++ b/src/Configuration/Metadata/Driver/AnnotationOrAttributeDriver.php @@ -86,9 +86,9 @@ private function parseExclusion(Annotation\Exclusion $exclusion): Exclusion { return new Exclusion( $exclusion->groups, - null !== $exclusion->sinceVersion ? (string)$exclusion->sinceVersion : null, - null !== $exclusion->untilVersion ? (string)$exclusion->untilVersion : null, - null !== $exclusion->maxDepth ? (int)$exclusion->maxDepth : null, + null !== $exclusion->sinceVersion ? (string) $exclusion->sinceVersion : null, + null !== $exclusion->untilVersion ? (string) $exclusion->untilVersion : null, + null !== $exclusion->maxDepth ? (int) $exclusion->maxDepth : null, $this->checkExpression($exclusion->excludeIf) ); } diff --git a/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php b/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php index 05cf1286..ea57bbd8 100644 --- a/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php +++ b/tests/Hateoas/Tests/Fixtures/UserPhpAttributes.php @@ -36,7 +36,8 @@ sinceVersion: '1.1', untilVersion: '2.3', maxDepth: 43, - excludeIf: 'bar') + excludeIf: 'bar' + ) ), exclusion: new Hateoas\Exclusion( groups: ['group1', 'group2'], From c2475120f84b21885e2df9ef10367d97ae631980 Mon Sep 17 00:00:00 2001 From: ixarlie Date: Sat, 13 Jan 2024 16:30:02 +0100 Subject: [PATCH 15/15] skip attribute driver for php lower than 8.1 --- .../Configuration/Metadata/Driver/AttributeDriverTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php index 46d559e3..98a6c105 100644 --- a/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php +++ b/tests/Hateoas/Tests/Configuration/Metadata/Driver/AttributeDriverTest.php @@ -9,6 +9,13 @@ class AttributeDriverTest extends AbstractDriverTest { + public function setUp(): void + { + if (PHP_VERSION_ID < 80100) { + $this->markTestSkipped('AttributeDriver is available as of PHP 8.1.0'); + } + } + public function createDriver() { return new AttributeDriver(