From e772e6fb64a5fa89a7181a8a9326745169d7c447 Mon Sep 17 00:00:00 2001 From: Yannick ROGER Date: Fri, 12 Jun 2020 15:42:39 +0200 Subject: [PATCH] Minimal compatibility with RAML 1.0 --- README.md | 9 ++++++++ composer.json | 2 +- src/APISpec/RAML.php | 17 +++++++++++++-- src/Parameter.php | 27 +++++++++++++++++------ src/RREST.php | 2 +- tests/fixture/song.raml | 13 +++++------ tests/units/Parameter.php | 46 +++++++++++++++++++++++++++++++++++++-- 7 files changed, 96 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 92894a2..7fb66c1 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,15 @@ ## Versions > Important: **RREST 2.0** is in active development. It doesn't cover RAML 1.0 completely. +### RAML 1.0 +RAML 1.0 is not covered completely. + +Known missing feature: +- Support date format that are not `datetime`. + +Limitations of RAML handling can be found in its [Parameter handling](https://github.com/RETFU/RREST/blob/master/src/Parameter.php). + +### RAML 0.8 For usage with RAML 0.8 please use RREST v1.x versions. diff --git a/composer.json b/composer.json index 8d59056..75f0229 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "symfony/serializer": "^3.0", "symfony/property-access": "^3.0", "symfony/yaml": "^3.0", - "raml-org/raml-php-parser": "^2.2", + "raml-org/raml-php-parser": "^4.6", "jrfnl/php-cast-to-type": "^2.0", "willdurand/negotiation": "^2.0", "ralouphie/getallheaders": "^2.0", diff --git a/src/APISpec/RAML.php b/src/APISpec/RAML.php index ca917db..8e0f07f 100644 --- a/src/APISpec/RAML.php +++ b/src/APISpec/RAML.php @@ -2,6 +2,8 @@ namespace RREST\APISpec; +use Raml\BodyInterface; +use Raml\WebFormBody; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Raml\ApiDefinition; @@ -36,7 +38,7 @@ class RAML implements APISpecInterface /** * @param ApiDefinition $apiDefinition * @param string $httpMethod - * @param strings $routePath (PHP_URL_PATH) + * @param string $routePath (PHP_URL_PATH) */ public function __construct(ApiDefinition $apiDefinition, $httpMethod, $routePath) { @@ -173,7 +175,13 @@ public function getRequestPayloadBodySchema($contentType) $bodies = $this->method->getBodies(); if (empty($bodies) === false) { try { - return (string) $this->method->getBodyByType($contentType)->getSchema(); + $body = $this->method->getBodyByType($contentType); + + if ($this->hasSchema($body)) { + return (string)$body->getSchema(); + } + + return ''; } catch (\Exception $e) { } } @@ -181,6 +189,11 @@ public function getRequestPayloadBodySchema($contentType) return false; } + private function hasSchema(BodyInterface $body): bool + { + return !($body instanceof WebFormBody); + } + /** * {@inheritdoc} */ diff --git a/src/Parameter.php b/src/Parameter.php index 72d715f..4dcd079 100644 --- a/src/Parameter.php +++ b/src/Parameter.php @@ -6,23 +6,29 @@ class Parameter { - const TYPE_STRING = 'string'; const TYPE_NUMBER = 'number'; - const TYPE_INTEGER = 'integer'; - const TYPE_DATE = 'date'; const TYPE_BOOLEAN = 'boolean'; + const TYPE_STRING = 'string'; + const TYPE_DATE_ONLY = 'date-only'; + const TYPE_TIME_ONLY = 'time-only'; + const TYPE_DATETIME_ONLY = 'datetime-only'; + const TYPE_DATETIME = 'datetime'; const TYPE_FILE = 'file'; + const TYPE_INTEGER = 'integer'; /** * @var string[] */ protected $validTypes = [ - self::TYPE_STRING, self::TYPE_NUMBER, - self::TYPE_INTEGER, - self::TYPE_DATE, + self::TYPE_STRING, self::TYPE_BOOLEAN, + self::TYPE_DATE_ONLY, + self::TYPE_TIME_ONLY, + self::TYPE_DATETIME_ONLY, + self::TYPE_DATETIME, self::TYPE_FILE, + self::TYPE_INTEGER, ]; /** @@ -266,11 +272,18 @@ public function assertValue($value) $this->throwInvalidParameter($this->getName().' is not a boolean'); } break; - case static::TYPE_DATE: + case static::TYPE_DATETIME: if ($value instanceof \DateTime === false) { $this->throwInvalidParameter($this->getName().' is not a valid date'); } break; + case static::TYPE_DATE_ONLY: + case static::TYPE_TIME_ONLY: + case static::TYPE_DATETIME_ONLY: + $this->throwInvalidParameter( + $this->getType().' is not supported yet in RREST. Use datetime or feel free to contribute it' + ); + break; case static::TYPE_STRING: if (!is_string($value)) { $this->throwInvalidParameter($this->getName().' is not a string'); diff --git a/src/RREST.php b/src/RREST.php index c65ca97..1899da2 100644 --- a/src/RREST.php +++ b/src/RREST.php @@ -418,7 +418,7 @@ private function cast($value, $type) $type = 'num'; } - if ($type != 'date') { + if ($type != 'datetime') { $castValue = \CastToType::cast($value, $type, false, true); } else { //Specific case for date diff --git a/tests/fixture/song.raml b/tests/fixture/song.raml index 6e6654f..0bbc7cf 100644 --- a/tests/fixture/song.raml +++ b/tests/fixture/song.raml @@ -1,4 +1,4 @@ -#%RAML 0.8 +#%RAML 1.0 title: World Music API baseUri: http://{bucketName}.api.com/{version} @@ -9,7 +9,7 @@ baseUriParameters: required: false version: v1 securitySchemes: - - JWT: + JWT: description: | https://jwt.io/introduction/ type: x-jwt @@ -23,9 +23,9 @@ securitySchemes: ``` type: string required: true -schemas: - - Song: !include song.json - - Person: | +types: + Song: !include song.json + Person: | { "$schema": "http://json-schema.org/schema", "type": "array", @@ -95,10 +95,9 @@ schemas: choice[]: description: Filter by choice type: string - repeat: true modificationDate: description: Modification date - type: date + type: datetime responses: 200: body: diff --git a/tests/units/Parameter.php b/tests/units/Parameter.php index 6343fe6..298cefc 100644 --- a/tests/units/Parameter.php +++ b/tests/units/Parameter.php @@ -126,8 +126,50 @@ function () { ->isInstanceOf('RREST\Exception\InvalidParameterException') ; - //cast type date - $this->newTestedInstance('name', 'date', true); + //cast type datetime + $this->newTestedInstance('name', 'datetime', true); + $this + ->exception( + function () { + $this + ->testedInstance + ->assertValue('test', 'test') + ; + } + ) + ->isInstanceOf('RREST\Exception\InvalidParameterException') + ; + + //cast type date-only + $this->newTestedInstance('name', 'date-only', true); + $this + ->exception( + function () { + $this + ->testedInstance + ->assertValue('test', 'test') + ; + } + ) + ->isInstanceOf('RREST\Exception\InvalidParameterException') + ; + + //cast type time-only + $this->newTestedInstance('name', 'time-only', true); + $this + ->exception( + function () { + $this + ->testedInstance + ->assertValue('test', 'test') + ; + } + ) + ->isInstanceOf('RREST\Exception\InvalidParameterException') + ; + + //cast type datetime-only + $this->newTestedInstance('name', 'datetime-only', true); $this ->exception( function () {