From 7c38ef4a0b43fd3e91a731848a71a7c4af51bbd7 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 19:36:03 -0600 Subject: [PATCH 1/8] Annotation-powered method registration --- .editorconfig | 22 ++++++++++ composer.json | 3 +- src/Annotation/JsonRpcMethod.php | 39 +++++++++++++++++ .../JsonRpcHttpServerExtension.php | 6 +-- .../JsonRpcMethodDefinitionHelper.php | 42 ++++++++++++++++++- 5 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 .editorconfig create mode 100644 src/Annotation/JsonRpcMethod.php diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..82266d7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +; top-most EditorConfig file +root = true + +; Unix-style newlines +[*] +charset = utf-8 +end_of_line = LF +insert_final_newline = true +trim_trailing_whitespace = true + +[*.php] +indent_style = space +indent_size = 4 + +[composer.{json,lock}] +indent_size = 2 + +[*.md] +max_line_length = 80 + +[COMMIT_EDITMSG] +max_line_length = 0 diff --git a/composer.json b/composer.json index 512a4b3..6f9c7db 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ }, "suggest": { "yoanm/symfony-jsonrpc-params-validator": "Symfony bundle for easy JSON-RPC params validation", - "yoanm/symfony-jsonrpc-http-server-doc": "JSON-RPC documentation Bundle" + "yoanm/symfony-jsonrpc-http-server-doc": "JSON-RPC documentation Bundle", + "doctrine/annotations": "Autowire methods using annotations in PHP > 8." }, "require": { "php": ">=7.2", diff --git a/src/Annotation/JsonRpcMethod.php b/src/Annotation/JsonRpcMethod.php new file mode 100644 index 0000000..1b490c4 --- /dev/null +++ b/src/Annotation/JsonRpcMethod.php @@ -0,0 +1,39 @@ + $value) { + $method = 'set'.str_replace('_', '', $key); + if (!method_exists($this, $method)) { + throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); + } + $this->$method($value); + } + } + + public function setName(string $name) + { + $this->name = $name; + } + + public function getName(): string { + return $this->name; + } +} diff --git a/src/DependencyInjection/JsonRpcHttpServerExtension.php b/src/DependencyInjection/JsonRpcHttpServerExtension.php index d71bfaf..6a8b34d 100644 --- a/src/DependencyInjection/JsonRpcHttpServerExtension.php +++ b/src/DependencyInjection/JsonRpcHttpServerExtension.php @@ -66,7 +66,7 @@ public function process(ContainerBuilder $container) { $this->bindJsonRpcServerDispatcher($container); $this->bindValidatorIfDefined($container); - $this->binJsonRpcMethods($container); + $this->bindJsonRpcMethods($container); } /** @@ -149,11 +149,11 @@ private function bindValidatorIfDefined(ContainerBuilder $container) : void /** * @param ContainerBuilder $container */ - private function binJsonRpcMethods(ContainerBuilder $container) : void + private function bindJsonRpcMethods(ContainerBuilder $container) : void { $mappingAwareServiceDefinitionList = $this->findAndValidateMappingAwareDefinitionList($container); - $jsonRpcMethodDefinitionList = (new JsonRpcMethodDefinitionHelper()) + $jsonRpcMethodDefinitionList = (new JsonRpcMethodDefinitionHelper($container)) ->findAndValidateJsonRpcMethodDefinition($container); $methodMappingList = []; diff --git a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php index b924c2d..a07c83d 100644 --- a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php +++ b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php @@ -1,7 +1,9 @@ annotationsEnabled = $container->has('routing.loader.annotation') + && class_exists('Doctrine\Common\Annotations\Annotation'); + if ($this->annotationsEnabled) { + $this->reader = new AnnotationReader(); + } + } + /** * @param ContainerBuilder $container * @@ -26,8 +43,29 @@ public function findAndValidateJsonRpcMethodDefinition(ContainerBuilder $contain $this->validateJsonRpcMethodDefinition($serviceId, $container->getDefinition($serviceId)); foreach ($tagAttributeList as $tagAttributeKey => $tagAttributeData) { - $this->validateJsonRpcMethodTagAttributes($serviceId, $tagAttributeData); - $methodName = $tagAttributeData[JsonRpcHttpServerExtension::JSONRPC_METHOD_TAG_METHOD_NAME_KEY]; + try { + $this->validateJsonRpcMethodTagAttributes($serviceId, $tagAttributeData); + $methodName = $tagAttributeData[JsonRpcHttpServerExtension::JSONRPC_METHOD_TAG_METHOD_NAME_KEY]; + } + catch (\LogicException $e) { + // Annotation routing loader is conditionally added by the framework + // bundle; if it's enabled, allow for our own annotation-based + // method discovery. + if ($this->annotationsEnabled) { + $reflection = $container->getReflectionClass($container->getDefinition($serviceId)->getClass()); + $annotation = $this->reader->getClassAnnotation($reflection, self::METHOD_ANNOTATION_CLASS); + if ($annotation) { + /** @var \Yoanm\SymfonyJsonRpcHttpServer\Annotation\JsonRpcMethod $annotation */ + $methodName = $annotation->getName(); + } + else { + throw $e; + } + } + else { + throw $e; + } + } $definitionList[$serviceId][] = $methodName; } } From 95a30db66ec4434f4b11e31202e386e7cfbaf8d4 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 19:41:19 -0600 Subject: [PATCH 2/8] Fix incorrect version constraint in package suggestion --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6f9c7db..3d00a74 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "suggest": { "yoanm/symfony-jsonrpc-params-validator": "Symfony bundle for easy JSON-RPC params validation", "yoanm/symfony-jsonrpc-http-server-doc": "JSON-RPC documentation Bundle", - "doctrine/annotations": "Autowire methods using annotations in PHP > 8." + "doctrine/annotations": "Autowire methods using annotations." }, "require": { "php": ">=7.2", From 08b4bcda9da3e4d3bd1fd63f1d6ee9cfdbbceba1 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 19:43:59 -0600 Subject: [PATCH 3/8] Make invocation of annotation reader safer --- src/DependencyInjection/JsonRpcMethodDefinitionHelper.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php index a07c83d..5745f80 100644 --- a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php +++ b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php @@ -1,7 +1,6 @@ annotationsEnabled = $container->has('routing.loader.annotation') - && class_exists('Doctrine\Common\Annotations\Annotation'); + && class_exists('Doctrine\Common\Annotations\AnnotationReader'); if ($this->annotationsEnabled) { - $this->reader = new AnnotationReader(); + $this->reader = new \Doctrine\Common\Annotations\AnnotationReader(); } } From da3748e6f8e95638c7fecb231f6505ab72fac624 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 21:40:20 -0600 Subject: [PATCH 4/8] Fix existing test run, still needs coverage for annotations --- .../DependencyInjection/JsonRpcMethodDefinitionHelperTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Functional/DependencyInjection/JsonRpcMethodDefinitionHelperTest.php b/tests/Functional/DependencyInjection/JsonRpcMethodDefinitionHelperTest.php index 4c05dab..7c1177a 100644 --- a/tests/Functional/DependencyInjection/JsonRpcMethodDefinitionHelperTest.php +++ b/tests/Functional/DependencyInjection/JsonRpcMethodDefinitionHelperTest.php @@ -16,8 +16,8 @@ class JsonRpcMethodDefinitionHelperTest extends AbstractTestClass protected function setUp(): void { - $this->helper = new JsonRpcMethodDefinitionHelper(); parent::setUp(); + $this->helper = new JsonRpcMethodDefinitionHelper($this->container); } public function testShouldManageJsonRpcMethodMappingFromTag() From 6c79222a50caf3e103fb261f0812819a3adb1c5a Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 21:45:36 -0600 Subject: [PATCH 5/8] Fix code style inspection --- src/Annotation/JsonRpcMethod.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Annotation/JsonRpcMethod.php b/src/Annotation/JsonRpcMethod.php index 1b490c4..face9a4 100644 --- a/src/Annotation/JsonRpcMethod.php +++ b/src/Annotation/JsonRpcMethod.php @@ -22,7 +22,9 @@ public function __construct(array $data) foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, static::class)); + throw new \BadMethodCallException( + sprintf('Unknown property "%s" on annotation "%s".', $key, static::class) + ); } $this->$method($value); } @@ -33,7 +35,8 @@ public function setName(string $name) $this->name = $name; } - public function getName(): string { + public function getName(): string + { return $this->name; } } From 1af4fa28aeb37b36d0d8e2bb6deda3e387fd528d Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 21:50:59 -0600 Subject: [PATCH 6/8] Remaining code style fixes --- .../JsonRpcMethodDefinitionHelper.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php index 5745f80..bba9c5f 100644 --- a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php +++ b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php @@ -19,7 +19,8 @@ class JsonRpcMethodDefinitionHelper private const METHOD_ANNOTATION_CLASS = 'Yoanm\\SymfonyJsonRpcHttpServer\\Annotation\\JsonRpcMethod'; - public function __construct(ContainerBuilder $container) { + public function __construct(ContainerBuilder $container) + { $this->annotationsEnabled = $container->has('routing.loader.annotation') && class_exists('Doctrine\Common\Annotations\AnnotationReader'); if ($this->annotationsEnabled) { @@ -45,8 +46,7 @@ public function findAndValidateJsonRpcMethodDefinition(ContainerBuilder $contain try { $this->validateJsonRpcMethodTagAttributes($serviceId, $tagAttributeData); $methodName = $tagAttributeData[JsonRpcHttpServerExtension::JSONRPC_METHOD_TAG_METHOD_NAME_KEY]; - } - catch (\LogicException $e) { + } catch (\LogicException $e) { // Annotation routing loader is conditionally added by the framework // bundle; if it's enabled, allow for our own annotation-based // method discovery. @@ -56,12 +56,10 @@ public function findAndValidateJsonRpcMethodDefinition(ContainerBuilder $contain if ($annotation) { /** @var \Yoanm\SymfonyJsonRpcHttpServer\Annotation\JsonRpcMethod $annotation */ $methodName = $annotation->getName(); - } - else { + } else { throw $e; } - } - else { + } else { throw $e; } } From a9975e92e670e8ebf3f5a3970c332a1de1214bf6 Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Wed, 19 May 2021 22:16:40 -0600 Subject: [PATCH 7/8] Include annotations library as dev dependency --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3d00a74..0713f0e 100644 --- a/composer.json +++ b/composer.json @@ -49,6 +49,7 @@ "matthiasnoback/symfony-config-test": "^3.0 || ^4.0", "symfony/framework-bundle": "^4.0 || ^5.0", "symfony/routing": "^4.0 || ^5.0", - "yoanm/php-unit-extended": "~1.0" + "yoanm/php-unit-extended": "~1.0", + "doctrine/annotations": "^1.13" } } From 11f29d9592dd0d8305886e810e0aac76368fc67e Mon Sep 17 00:00:00 2001 From: Brad Jones Date: Thu, 20 May 2021 11:03:04 -0600 Subject: [PATCH 8/8] Address PR feedback --- src/Annotation/JsonRpcMethod.php | 1 + .../JsonRpcMethodDefinitionHelper.php | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Annotation/JsonRpcMethod.php b/src/Annotation/JsonRpcMethod.php index face9a4..bad8a90 100644 --- a/src/Annotation/JsonRpcMethod.php +++ b/src/Annotation/JsonRpcMethod.php @@ -10,6 +10,7 @@ */ class JsonRpcMethod { + /** @var string */ private $name; /** diff --git a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php index bba9c5f..d215c47 100644 --- a/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php +++ b/src/DependencyInjection/JsonRpcMethodDefinitionHelper.php @@ -2,10 +2,11 @@ namespace Yoanm\SymfonyJsonRpcHttpServer\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\LogicException; use Yoanm\JsonRpcServer\Domain\JsonRpcMethodInterface; +use Yoanm\SymfonyJsonRpcHttpServer\Annotation; +use Doctrine\Common\Annotations\AnnotationReader; /** * Class JsonRpcMethodDefinitionHelper @@ -13,18 +14,18 @@ class JsonRpcMethodDefinitionHelper { + /** @var bool */ private $annotationsEnabled; + /** @var \Doctrine\Common\Annotations\AnnotationReader|null */ private $reader; - private const METHOD_ANNOTATION_CLASS = 'Yoanm\\SymfonyJsonRpcHttpServer\\Annotation\\JsonRpcMethod'; - public function __construct(ContainerBuilder $container) { $this->annotationsEnabled = $container->has('routing.loader.annotation') && class_exists('Doctrine\Common\Annotations\AnnotationReader'); if ($this->annotationsEnabled) { - $this->reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $this->reader = new AnnotationReader(); } } @@ -52,8 +53,8 @@ public function findAndValidateJsonRpcMethodDefinition(ContainerBuilder $contain // method discovery. if ($this->annotationsEnabled) { $reflection = $container->getReflectionClass($container->getDefinition($serviceId)->getClass()); - $annotation = $this->reader->getClassAnnotation($reflection, self::METHOD_ANNOTATION_CLASS); - if ($annotation) { + $annotation = $this->reader->getClassAnnotation($reflection, Annotation\JsonRpcMethod::class); + if (null !== $annotation) { /** @var \Yoanm\SymfonyJsonRpcHttpServer\Annotation\JsonRpcMethod $annotation */ $methodName = $annotation->getName(); } else {