From f2c75ebc9de33dfd46009aa378470ef14333532a Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Thu, 11 Mar 2021 19:06:17 +0100 Subject: [PATCH 1/9] Fix Open API doc for DateTime requirements When using the following requierement: ``` @Rest\QueryParam(name="updatedFrom", strict=true, nullable=true, requirements=@Constraints\DateTime("Y-m-d\TH:i:s")) ``` According to the OpenAPI 3.0 documentation https://swagger.io/specification/, we should have "format": "date-time" rather than "format": "DateTime" in the generated doc --- RouteDescriber/FosRestDescriber.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index 8f3e814..cc07217 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -18,6 +18,7 @@ use Nelmio\ApiDocBundle\OpenApiPhp\Util; use OpenApi\Annotations as OA; use Symfony\Component\Routing\Route; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Constraints\Regex; final class FosRestDescriber implements RouteDescriberInterface @@ -104,6 +105,11 @@ final class FosRestDescriber implements RouteDescriberInterface private function getFormat($requirements) { if ($requirements instanceof Constraint && !$requirements instanceof Regex) { + + if ($requirements instanceof DateTime) { + return 'date-time'; + } + $reflectionClass = new \ReflectionClass($requirements); return $reflectionClass->getShortName(); From 7f9b00d62007dd397aa5622072a8e51d24d14571 Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Tue, 16 Mar 2021 10:40:12 +0100 Subject: [PATCH 2/9] Code improvements and add unit test --- RouteDescriber/FosRestDescriber.php | 7 ++++++- Tests/Functional/Controller/FOSRestController.php | 3 +++ Tests/Functional/FOSRestTest.php | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index cc07217..4b9f8fc 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -107,7 +107,12 @@ final class FosRestDescriber implements RouteDescriberInterface if ($requirements instanceof Constraint && !$requirements instanceof Regex) { if ($requirements instanceof DateTime) { - return 'date-time'; + // As defined per RFC3339 + if ($requirements->format === 'Y-m-d\TH:i:s') { + return 'date-time'; + } else if ($requirements->format === 'Y-m-d') { + return 'date'; + } } $reflectionClass = new \ReflectionClass($requirements); diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index ada65d4..ab2c66c 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -14,6 +14,7 @@ namespace Nelmio\ApiDocBundle\Tests\Functional\Controller; use FOS\RestBundle\Controller\Annotations\QueryParam; use FOS\RestBundle\Controller\Annotations\RequestParam; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Validator\Constraints\DateTime; use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Regex; @@ -28,6 +29,8 @@ class FOSRestController * @QueryParam(name="mapped", map=true) * @RequestParam(name="Barraa", key="bar", requirements="\d+") * @RequestParam(name="baz", requirements=@IsTrue) + * @RequestParam(name="datetime", requirements=@DateTime("Y-m-d\TH:i:s")) + * @RequestParam(name="date", requirements=@DateTime("Y-m-d")) */ public function fosrestAction() { diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index 7c9c5a3..a67cb7d 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -50,6 +50,12 @@ class FOSRestTest extends WebTestCase $this->assertEquals(OA\UNDEFINED, $bazProperty->pattern); $this->assertEquals('IsTrue', $bazProperty->format); + $barProperty = $this->getProperty($bodySchema, 'datetime'); + $this->assertEquals('date-time', $barProperty->format); + + $barProperty = $this->getProperty($bodySchema, 'date'); + $this->assertEquals('date', $barProperty->format); + // The _format path attribute should be removed $this->assertNotHasParameter('_format', 'path', $operation); } From 73ad2e3cdf5bcd8d35f60effb2465ed9ee6fd06f Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Tue, 16 Mar 2021 10:42:37 +0100 Subject: [PATCH 3/9] Fix property naming --- Tests/Functional/FOSRestTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index a67cb7d..739b0f3 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -50,11 +50,11 @@ class FOSRestTest extends WebTestCase $this->assertEquals(OA\UNDEFINED, $bazProperty->pattern); $this->assertEquals('IsTrue', $bazProperty->format); - $barProperty = $this->getProperty($bodySchema, 'datetime'); - $this->assertEquals('date-time', $barProperty->format); + $dateTimeProperty = $this->getProperty($bodySchema, 'datetime'); + $this->assertEquals('date-time', $dateTimeProperty->format); - $barProperty = $this->getProperty($bodySchema, 'date'); - $this->assertEquals('date', $barProperty->format); + $dateProperty = $this->getProperty($bodySchema, 'date'); + $this->assertEquals('date', $dateProperty->format); // The _format path attribute should be removed $this->assertNotHasParameter('_format', 'path', $operation); From a945a47e32746012705b9a2b6a7a3598a7f58592 Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Tue, 16 Mar 2021 10:46:21 +0100 Subject: [PATCH 4/9] CS Fixes --- RouteDescriber/FosRestDescriber.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index 4b9f8fc..5d9770f 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -105,16 +105,16 @@ final class FosRestDescriber implements RouteDescriberInterface private function getFormat($requirements) { if ($requirements instanceof Constraint && !$requirements instanceof Regex) { - + if ($requirements instanceof DateTime) { // As defined per RFC3339 - if ($requirements->format === 'Y-m-d\TH:i:s') { + if ('Y-m-d\TH:i:s' === $requirements->format) { return 'date-time'; - } else if ($requirements->format === 'Y-m-d') { + } elseif ('Y-m-d' === $requirements->format) { return 'date'; } } - + $reflectionClass = new \ReflectionClass($requirements); return $reflectionClass->getShortName(); From 56d4b78bf12433bf0d4f4cd356b3e98798c56a62 Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Tue, 16 Mar 2021 10:48:12 +0100 Subject: [PATCH 5/9] CS Fix --- RouteDescriber/FosRestDescriber.php | 1 - 1 file changed, 1 deletion(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index 5d9770f..d800e0b 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -105,7 +105,6 @@ final class FosRestDescriber implements RouteDescriberInterface private function getFormat($requirements) { if ($requirements instanceof Constraint && !$requirements instanceof Regex) { - if ($requirements instanceof DateTime) { // As defined per RFC3339 if ('Y-m-d\TH:i:s' === $requirements->format) { From a72588861f15b0c269105655f6fefb80a6b3a5ef Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Tue, 16 Mar 2021 11:05:00 +0100 Subject: [PATCH 6/9] Add support for 'c' format --- RouteDescriber/FosRestDescriber.php | 2 +- Tests/Functional/Controller/FOSRestController.php | 1 + Tests/Functional/FOSRestTest.php | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index d800e0b..fd92f84 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -107,7 +107,7 @@ final class FosRestDescriber implements RouteDescriberInterface if ($requirements instanceof Constraint && !$requirements instanceof Regex) { if ($requirements instanceof DateTime) { // As defined per RFC3339 - if ('Y-m-d\TH:i:s' === $requirements->format) { + if ('Y-m-d\TH:i:s' === $requirements->format || 'c' === $requirements->format) { return 'date-time'; } elseif ('Y-m-d' === $requirements->format) { return 'date'; diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index ab2c66c..2857f28 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -30,6 +30,7 @@ class FOSRestController * @RequestParam(name="Barraa", key="bar", requirements="\d+") * @RequestParam(name="baz", requirements=@IsTrue) * @RequestParam(name="datetime", requirements=@DateTime("Y-m-d\TH:i:s")) + * @RequestParam(name="datetimeAlt", requirements=@DateTime("c")) * @RequestParam(name="date", requirements=@DateTime("Y-m-d")) */ public function fosrestAction() diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index 739b0f3..8024011 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -53,6 +53,9 @@ class FOSRestTest extends WebTestCase $dateTimeProperty = $this->getProperty($bodySchema, 'datetime'); $this->assertEquals('date-time', $dateTimeProperty->format); + $dateTimeAltProperty = $this->getProperty($bodySchema, 'datetimeAlt'); + $this->assertEquals('date-time', $dateTimeAltProperty->format); + $dateProperty = $this->getProperty($bodySchema, 'date'); $this->assertEquals('date', $dateProperty->format); From 0e7ebe5650171c30b0ddde6e5c2a12c005ed89b0 Mon Sep 17 00:00:00 2001 From: tlallement Date: Wed, 24 Mar 2021 18:01:32 +0100 Subject: [PATCH 7/9] Small fixes for RFC3339 and new assertion --- RouteDescriber/FosRestDescriber.php | 4 +++- Tests/Functional/Controller/FOSRestController.php | 3 ++- Tests/Functional/FOSRestTest.php | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index fd92f84..626f6a7 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -107,10 +107,12 @@ final class FosRestDescriber implements RouteDescriberInterface if ($requirements instanceof Constraint && !$requirements instanceof Regex) { if ($requirements instanceof DateTime) { // As defined per RFC3339 - if ('Y-m-d\TH:i:s' === $requirements->format || 'c' === $requirements->format) { + if (\DateTimeInterface::RFC3339 === $requirements->format || 'c' === $requirements->format) { return 'date-time'; } elseif ('Y-m-d' === $requirements->format) { return 'date'; + } else { + return null; } } diff --git a/Tests/Functional/Controller/FOSRestController.php b/Tests/Functional/Controller/FOSRestController.php index 2857f28..772af46 100644 --- a/Tests/Functional/Controller/FOSRestController.php +++ b/Tests/Functional/Controller/FOSRestController.php @@ -29,8 +29,9 @@ class FOSRestController * @QueryParam(name="mapped", map=true) * @RequestParam(name="Barraa", key="bar", requirements="\d+") * @RequestParam(name="baz", requirements=@IsTrue) - * @RequestParam(name="datetime", requirements=@DateTime("Y-m-d\TH:i:s")) + * @RequestParam(name="datetime", requirements=@DateTime("Y-m-d\TH:i:sP")) * @RequestParam(name="datetimeAlt", requirements=@DateTime("c")) + * @RequestParam(name="datetimeNoFormat", requirements=@DateTime()) * @RequestParam(name="date", requirements=@DateTime("Y-m-d")) */ public function fosrestAction() diff --git a/Tests/Functional/FOSRestTest.php b/Tests/Functional/FOSRestTest.php index 8024011..66917b8 100644 --- a/Tests/Functional/FOSRestTest.php +++ b/Tests/Functional/FOSRestTest.php @@ -56,6 +56,9 @@ class FOSRestTest extends WebTestCase $dateTimeAltProperty = $this->getProperty($bodySchema, 'datetimeAlt'); $this->assertEquals('date-time', $dateTimeAltProperty->format); + $dateTimeNoFormatProperty = $this->getProperty($bodySchema, 'datetimeNoFormat'); + $this->assertEquals(OA\UNDEFINED, $dateTimeNoFormatProperty->format); + $dateProperty = $this->getProperty($bodySchema, 'date'); $this->assertEquals('date', $dateProperty->format); From d6a2d1240a853262a8005f6e4d8533127e1101f7 Mon Sep 17 00:00:00 2001 From: tlallement Date: Wed, 24 Mar 2021 18:10:45 +0100 Subject: [PATCH 8/9] Fix for PHP 7.1 --- RouteDescriber/FosRestDescriber.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index 626f6a7..9d39899 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -107,7 +107,7 @@ final class FosRestDescriber implements RouteDescriberInterface if ($requirements instanceof Constraint && !$requirements instanceof Regex) { if ($requirements instanceof DateTime) { // As defined per RFC3339 - if (\DateTimeInterface::RFC3339 === $requirements->format || 'c' === $requirements->format) { + if (\DateTime::RFC3339 === $requirements->format || 'c' === $requirements->format) { return 'date-time'; } elseif ('Y-m-d' === $requirements->format) { return 'date'; From 14975b314053a77a175af93984094cce6618b93b Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Fri, 26 Mar 2021 22:51:40 +0100 Subject: [PATCH 9/9] Update RouteDescriber/FosRestDescriber.php Co-authored-by: Javier Spagnoletti --- RouteDescriber/FosRestDescriber.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/RouteDescriber/FosRestDescriber.php b/RouteDescriber/FosRestDescriber.php index 9d39899..1dede6b 100644 --- a/RouteDescriber/FosRestDescriber.php +++ b/RouteDescriber/FosRestDescriber.php @@ -109,11 +109,13 @@ final class FosRestDescriber implements RouteDescriberInterface // As defined per RFC3339 if (\DateTime::RFC3339 === $requirements->format || 'c' === $requirements->format) { return 'date-time'; - } elseif ('Y-m-d' === $requirements->format) { - return 'date'; - } else { - return null; } + + if ('Y-m-d' === $requirements->format) { + return 'date'; + } + + return null; } $reflectionClass = new \ReflectionClass($requirements);