From 285567c39088b6e4d1bb1b30dd9f9afc6bc5af41 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Fri, 4 Aug 2023 14:27:01 +0100 Subject: [PATCH 1/8] Updated php fixer to version 3 --- .gitignore | 1 + .php_cs.dist => .php-cs-fixer.dist.php | 2 +- Makefile | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename .php_cs.dist => .php-cs-fixer.dist.php (92%) diff --git a/.gitignore b/.gitignore index c86af6f..fa1d02a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /node_modules /.php_cs.cache +/.php-cs-fixer.cache /.phpunit.result.cache php-cs-fixer.phar diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 92% rename from .php_cs.dist rename to .php-cs-fixer.dist.php index 704f437..f3585f2 100644 --- a/.php_cs.dist +++ b/.php-cs-fixer.dist.php @@ -1,6 +1,6 @@ setRules([ '@PSR2' => true, 'array_syntax' => ['syntax' => 'short'], diff --git a/Makefile b/Makefile index ee99b2a..b4fae49 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ check-style: php-cs-fixer.phar fix-style: php-cs-fixer.phar $(DOCKER_PHP) vendor/bin/indent --tabs composer.json - $(DOCKER_PHP) vendor/bin/indent --spaces .php_cs.dist + $(DOCKER_PHP) vendor/bin/indent --spaces .php-cs-fixer.dist.php $(DOCKER_PHP) ./php-cs-fixer.phar fix src/ --diff install: composer.lock yarn.lock From bbe3aa57aecefd29d4f232b94c1d6e9d22d2e31e Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Fri, 4 Aug 2023 14:30:34 +0100 Subject: [PATCH 2/8] Added functions to remove properties in components --- src/ReferenceContext.php | 6 +- src/json/JsonPointer.php | 10 +- src/spec/Components.php | 52 ++++++ src/spec/Encoding.php | 1 - src/spec/OAuthFlow.php | 1 - src/spec/Operation.php | 1 - src/spec/Reference.php | 2 +- src/spec/Type.php | 14 +- tests/spec/ComponentsTest.php | 297 ++++++++++++++++++++++++++++------ 9 files changed, 319 insertions(+), 65 deletions(-) diff --git a/src/ReferenceContext.php b/src/ReferenceContext.php index bde0a96..514174e 100644 --- a/src/ReferenceContext.php +++ b/src/ReferenceContext.php @@ -23,11 +23,11 @@ class ReferenceContext * The result will be a single API description file with references * inside of the file structure. */ - const RESOLVE_MODE_INLINE = 'inline'; + public const RESOLVE_MODE_INLINE = 'inline'; /** * resolve all references, except recursive ones. */ - const RESOLVE_MODE_ALL = 'all'; + public const RESOLVE_MODE_ALL = 'all'; /** * @var bool whether to throw UnresolvableReferenceException in case a reference can not @@ -103,7 +103,7 @@ private function buildUri($parts) $host = $parts['host'] ?? ''; $port = !empty($parts['port']) ? ':' . $parts['port'] : ''; $user = $parts['user'] ?? ''; - $pass = !empty($parts['pass']) ? ':' . $parts['pass'] : ''; + $pass = !empty($parts['pass']) ? ':' . $parts['pass'] : ''; $pass = ($user || $pass) ? "$pass@" : ''; $path = $parts['path'] ?? ''; $query = !empty($parts['query']) ? '?' . $parts['query'] : ''; diff --git a/src/json/JsonPointer.php b/src/json/JsonPointer.php index 0e1f75e..3121e08 100644 --- a/src/json/JsonPointer.php +++ b/src/json/JsonPointer.php @@ -107,11 +107,11 @@ public function evaluate($jsonDocument) foreach ($this->getPath() as $part) { if (is_array($currentReference)) { -// if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { -// throw new NonexistentJsonPointerReferenceException( -// "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." -// ); -// } + // if (!preg_match('~^([1-9]*[0-9]|-)$~', $part)) { + // throw new NonexistentJsonPointerReferenceException( + // "Failed to evaluate pointer '$this->_pointer'. Invalid pointer path '$part' for Array at path '$currentPath'." + // ); + // } if ($part === '-' || !array_key_exists($part, $currentReference)) { throw new NonexistentJsonPointerReferenceException( "Failed to evaluate pointer '$this->_pointer'. Array has no member $part at path '$currentPath'." diff --git a/src/spec/Components.php b/src/spec/Components.php index c7e7dc1..c87f1cd 100644 --- a/src/spec/Components.php +++ b/src/spec/Components.php @@ -31,6 +31,58 @@ */ class Components extends SpecBaseObject { + /** + * @param string $name schema name + */ + public function removeSchema(string $name): void + { + $this->deleteProperty('schemas', $name); + } + + /** + * @param string $name parameter name + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', $name); + } + + /** + * @param string $name response name + */ + public function removeResponse(string $name): void + { + $this->deleteProperty('responses', $name); + } + + /** + * @param string $name securityScheme name + */ + public function removeSecuityScheme(string $name): void + { + $this->deleteProperty('securitySchemes', $name); + } + + /** + * @param string $name request body name + */ + public function removeRequestBody(string $name): void + { + $this->deleteProperty('requestBodies', $name); + } + + + protected function deleteProperty($key, $name = null): void + { + if(is_array($this->$key)) { + if($name && !empty($this->$key[$name])) { + $properties = $this->$key; + unset($properties[$name]); + $this->$key = $properties; + } + } + } + /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Encoding.php b/src/spec/Encoding.php index 865f560..f4448f0 100644 --- a/src/spec/Encoding.php +++ b/src/spec/Encoding.php @@ -23,7 +23,6 @@ */ class Encoding extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ diff --git a/src/spec/OAuthFlow.php b/src/spec/OAuthFlow.php index a32536d..114caf2 100644 --- a/src/spec/OAuthFlow.php +++ b/src/spec/OAuthFlow.php @@ -21,7 +21,6 @@ */ class OAuthFlow extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Operation.php b/src/spec/Operation.php index b052532..7bf13dd 100644 --- a/src/spec/Operation.php +++ b/src/spec/Operation.php @@ -29,7 +29,6 @@ */ class Operation extends SpecBaseObject { - /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Reference.php b/src/spec/Reference.php index cda612a..2f919a6 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -154,7 +154,7 @@ public function setContext(ReferenceContext $context) /** * @return ReferenceContext */ - public function getContext() : ?ReferenceContext + public function getContext(): ?ReferenceContext { return $this->_context; } diff --git a/src/spec/Type.php b/src/spec/Type.php index 9861000..0926caf 100644 --- a/src/spec/Type.php +++ b/src/spec/Type.php @@ -14,13 +14,13 @@ */ class Type { - const ANY = 'any'; - const INTEGER = 'integer'; - const NUMBER = 'number'; - const STRING = 'string'; - const BOOLEAN = 'boolean'; - const OBJECT = 'object'; - const ARRAY = 'array'; + public const ANY = 'any'; + public const INTEGER = 'integer'; + public const NUMBER = 'number'; + public const STRING = 'string'; + public const BOOLEAN = 'boolean'; + public const OBJECT = 'object'; + public const ARRAY = 'array'; /** * Indicate whether a type is a scalar type, i.e. not an array or object. diff --git a/tests/spec/ComponentsTest.php b/tests/spec/ComponentsTest.php index 6418c34..e41e4e2 100644 --- a/tests/spec/ComponentsTest.php +++ b/tests/spec/ComponentsTest.php @@ -8,10 +8,11 @@ */ class ComponentsTest extends \PHPUnit\Framework\TestCase { - public function testRead() - { - /** @var $components Components */ - $components = Reader::readFromYaml(<<<'YAML' + public function testRead() + { + /** @var $components Components */ + $components = Reader::readFromYaml( + <<<'YAML' schemas: GeneralError: type: object @@ -78,48 +79,252 @@ public function testRead() scopes: write:pets: modify pets in your account read:pets: read your pets -YAML - , Components::class); - - $result = $components->validate(); - $this->assertEquals([], $components->getErrors()); - $this->assertTrue($result); - - $this->assertAllInstanceOf(\cebe\openapi\spec\Schema::class, $components->schemas); - $this->assertCount(3, $components->schemas); - $this->assertArrayHasKey('GeneralError', $components->schemas); - $this->assertArrayHasKey('Category', $components->schemas); - $this->assertArrayHasKey('Tag', $components->schemas); - $this->assertAllInstanceOf(\cebe\openapi\spec\Response::class, $components->responses); - $this->assertCount(3, $components->responses); - $this->assertArrayHasKey('NotFound', $components->responses); - $this->assertArrayHasKey('IllegalInput', $components->responses); - $this->assertArrayHasKey('GeneralError', $components->responses); - $this->assertAllInstanceOf(\cebe\openapi\spec\Parameter::class, $components->parameters); - $this->assertCount(2, $components->parameters); - $this->assertArrayHasKey('skipParam', $components->parameters); - $this->assertArrayHasKey('limitParam', $components->parameters); - $this->assertAllInstanceOf(\cebe\openapi\spec\Example::class, $components->examples); - $this->assertCount(0, $components->examples); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\RequestBody::class, $components->requestBodies); - $this->assertCount(0, $components->requestBodies); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\Header::class, $components->headers); - $this->assertCount(0, $components->headers); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\SecurityScheme::class, $components->securitySchemes); - $this->assertCount(2, $components->securitySchemes); - $this->assertArrayHasKey('api_key', $components->securitySchemes); - $this->assertArrayHasKey('petstore_auth', $components->securitySchemes); - $this->assertAllInstanceOf(\cebe\openapi\spec\Link::class, $components->links); - $this->assertCount(0, $components->links); // TODO - $this->assertAllInstanceOf(\cebe\openapi\spec\Callback::class, $components->callbacks); - $this->assertCount(0, $components->callbacks); // TODO - } +YAML, + Components::class + ); + + $result = $components->validate(); + $this->assertEquals([], $components->getErrors()); + $this->assertTrue($result); - public function assertAllInstanceOf($className, $array) - { - foreach($array as $k => $v) { - $this->assertInstanceOf($className, $v, "Asserting that item with key '$k' is instance of $className"); - } + $this->assertAllInstanceOf(\cebe\openapi\spec\Schema::class, $components->schemas); + $this->assertCount(3, $components->schemas); + $this->assertArrayHasKey('GeneralError', $components->schemas); + $this->assertArrayHasKey('Category', $components->schemas); + $this->assertArrayHasKey('Tag', $components->schemas); + $this->assertAllInstanceOf(\cebe\openapi\spec\Response::class, $components->responses); + $this->assertCount(3, $components->responses); + $this->assertArrayHasKey('NotFound', $components->responses); + $this->assertArrayHasKey('IllegalInput', $components->responses); + $this->assertArrayHasKey('GeneralError', $components->responses); + $this->assertAllInstanceOf(\cebe\openapi\spec\Parameter::class, $components->parameters); + $this->assertCount(2, $components->parameters); + $this->assertArrayHasKey('skipParam', $components->parameters); + $this->assertArrayHasKey('limitParam', $components->parameters); + $this->assertAllInstanceOf(\cebe\openapi\spec\Example::class, $components->examples); + $this->assertCount(0, $components->examples); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\RequestBody::class, $components->requestBodies); + $this->assertCount(0, $components->requestBodies); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\Header::class, $components->headers); + $this->assertCount(0, $components->headers); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\SecurityScheme::class, $components->securitySchemes); + $this->assertCount(2, $components->securitySchemes); + $this->assertArrayHasKey('api_key', $components->securitySchemes); + $this->assertArrayHasKey('petstore_auth', $components->securitySchemes); + $this->assertAllInstanceOf(\cebe\openapi\spec\Link::class, $components->links); + $this->assertCount(0, $components->links); // TODO + $this->assertAllInstanceOf(\cebe\openapi\spec\Callback::class, $components->callbacks); + $this->assertCount(0, $components->callbacks); // TODO + } + + public function assertAllInstanceOf($className, $array) + { + foreach ($array as $k => $v) { + $this->assertInstanceOf($className, $v, "Asserting that item with key '$k' is instance of $className"); } + } + + /** + * Test Delete a named schema + */ + public function testDeleteSchema() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->schemas), 3); + $this->assertTrue(!empty($components->schemas['GeneralError'])); + + $components->removeSchema('GeneralError'); + $this->assertEquals(count($components->schemas), 2); + $this->assertTrue(empty($components->schemas['GeneralError'])); + + $components->removeSchema('Tag'); + $this->assertEquals(count($components->schemas), 1); + $this->assertTrue(empty($components->schemas['Tag'])); + } + + + /** + * Test Delete a named parameter + */ + public function testDeleteParameter() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->parameters), 2); + $this->assertTrue(!empty($components->parameters['skipParam'])); + + $components->removeParameter('skipParam'); + $this->assertEquals(count($components->parameters), 1); + $this->assertTrue(empty($components->parameters['skipParam'])); + + $components->removeParameter('limitParam'); + $this->assertEquals(count($components->parameters), 0); + $this->assertTrue(empty($components->parameters['limitParam'])); + } + + /** + * Test Delete a named response + */ + public function testDeleteResponse() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->responses), 3); + $this->assertTrue(!empty($components->responses['NotFound'])); + + $components->removeResponse('NotFound'); + $this->assertEquals(count($components->responses), 2); + $this->assertTrue(empty($components->responses['NotFound'])); + + $components->removeResponse('GeneralError'); + $this->assertEquals(count($components->responses), 1); + $this->assertTrue(empty($components->responses['GeneralError'])); + } + + /** + * Test Delete a named request body + */ + public function testDeleteRequestBodies() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->requestBodies), 3); + $this->assertTrue(!empty($components->requestBodies['req1'])); + + $components->removeRequestBody('req1'); + $this->assertEquals(count($components->requestBodies), 2); + $this->assertTrue(empty($components->requestBodies['req1'])); + + $components->removeRequestBody('req2'); + $this->assertEquals(count($components->requestBodies), 1); + $this->assertTrue(empty($components->requestBodies['req2'])); + } + + /** + * Test Delete a named security scheme + */ + public function testDeletesecuritySchemes() + { + $components = $this->componentData(); + + $this->assertEquals(count($components->securitySchemes), 2); + $this->assertTrue(!empty($components->securitySchemes['api_key'])); + + $components->removeSecuityScheme('api_key'); + $this->assertEquals(count($components->securitySchemes), 1); + $this->assertTrue(empty($components->securitySchemes['api_key'])); + + } + + protected function componentData(): Components + { + $components = Reader::readFromYaml( + <<<'YAML' + schemas: + GeneralError: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + parameters: + skipParam: + name: skip + in: query + description: number of items to skip + required: true + schema: + type: integer + format: int32 + limitParam: + name: limit + in: query + description: max records to return + required: true + schema: + type: integer + format: int32 + responses: + NotFound: + description: Entity not found. + IllegalInput: + description: Illegal input for operation. + GeneralError: + description: General Error + content: + application/json: + schema: + $ref: '#/components/schemas/GeneralError' + securitySchemes: + api_key: + type: apiKey + name: api_key + in: header + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: http://example.org/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + requestBodies: + req1: + description: 'Request one' + required: true + content: + application/vnd.api+json: + schema: + type: object + properties: + data: + type: array + + req2: + description: 'Request two' + required: true + content: + application/vnd.api+json: + schema: + type: object + properties: + data: + type: array + + req3: + description: 'Request three' + required: true + content: + application/vnd.api+json: + schema: + type: object + YAML, + Components::class + ); + + $result = $components->validate(); + $this->assertEquals([], $components->getErrors()); + $this->assertTrue($result); -} \ No newline at end of file + return $components; + } +} From 12833f63814538ba5bedf0b69aabba12eb368123 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Mon, 7 Aug 2023 16:16:15 +0100 Subject: [PATCH 3/8] Implementing functions to remove elements --- src/SpecBaseObject.php | 34 ++++++++++++++++++++++++++++++++++ src/spec/Components.php | 12 ------------ src/spec/Link.php | 8 ++++++++ src/spec/MediaType.php | 16 ++++++++++++++++ src/spec/OAuthFlow.php | 8 ++++++++ src/spec/OpenApi.php | 25 +++++++++++++++++++++++++ src/spec/Operation.php | 35 +++++++++++++++++++++++++++++++++++ tests/spec/HeaderTest.php | 5 +++++ tests/spec/InfoTest.php | 4 ++++ tests/spec/LinkTest.php | 8 ++++++++ tests/spec/MediaTypeTest.php | 4 ++++ tests/spec/OpenApiTest.php | 6 ++++++ tests/spec/OperationTest.php | 12 ++++++++++++ 13 files changed, 165 insertions(+), 12 deletions(-) diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 1de429b..45eefa7 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -348,6 +348,32 @@ protected function validateUrl(string $property) } } + + protected function deleteProperty($key, $name = null, $value = null): void + { + if(is_array($this->$key) && $name) { + $this->_properties[$key] = $this->_removeKey($this->$key, $name, $value); + }else{ + $this->_properties = $this->_removeKey($this->_properties, $key); + } + } + + private function _removeKey(array $arrayData, String $name, $value = null): array { + if(!empty($arrayData[$name])) { + $properties = $arrayData; + unset($properties[$name]); + return $properties; + } + foreach($arrayData as $key => $val){ + if($name === $val){ + unset($arrayData[$key]); + }elseif($val instanceof self && !empty($val->$name) && $val->$name === $value){ + unset($arrayData[$key]); + } + } + return $arrayData; + } + public function __get($name) { if (isset($this->_properties[$name])) { @@ -525,4 +551,12 @@ public function getExtensions(): array } return $extensions; } + + /** + * Remove a property or an attribute + * @param string $name name of property to be removed + */ + public function removeProperty($name){ + $this->deleteProperty($name); + } } diff --git a/src/spec/Components.php b/src/spec/Components.php index c87f1cd..44088e4 100644 --- a/src/spec/Components.php +++ b/src/spec/Components.php @@ -71,18 +71,6 @@ public function removeRequestBody(string $name): void $this->deleteProperty('requestBodies', $name); } - - protected function deleteProperty($key, $name = null): void - { - if(is_array($this->$key)) { - if($name && !empty($this->$key[$name])) { - $properties = $this->$key; - unset($properties[$name]); - $this->$key = $properties; - } - } - } - /** * @return array array of attributes available in this object. */ diff --git a/src/spec/Link.php b/src/spec/Link.php index 9d21c2a..ffffe8d 100644 --- a/src/spec/Link.php +++ b/src/spec/Link.php @@ -48,4 +48,12 @@ protected function performValidation() $this->addError('Link: operationId and operationRef are mutually exclusive.'); } } + + /** + * @param string $name parameter name + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', $name); + } } diff --git a/src/spec/MediaType.php b/src/spec/MediaType.php index 326f8c5..4df3db2 100644 --- a/src/spec/MediaType.php +++ b/src/spec/MediaType.php @@ -72,6 +72,22 @@ public function __construct(array $data) } } + /** + * @param string $name example name + */ + public function removeExample(string $name): void + { + $this->deleteProperty('examples', $name); + } + + /** + * @param string $name example name + */ + public function removeEncoding(string $name): void + { + $this->deleteProperty('encoding', $name); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. */ diff --git a/src/spec/OAuthFlow.php b/src/spec/OAuthFlow.php index 114caf2..d6e1737 100644 --- a/src/spec/OAuthFlow.php +++ b/src/spec/OAuthFlow.php @@ -34,6 +34,14 @@ protected function attributes(): array ]; } + /** + * @param string $name scope's name + */ + public function removeScope(string $name): void + { + $this->deleteProperty('scopes', $name); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. * diff --git a/src/spec/OpenApi.php b/src/spec/OpenApi.php index 29d38b3..8f2f8fe 100644 --- a/src/spec/OpenApi.php +++ b/src/spec/OpenApi.php @@ -44,6 +44,31 @@ protected function attributes(): array ]; } + /** + * @param string $name name of security requirement + */ + public function removeSecurity(string $name): void + { + $this->deleteProperty('security', $name); + } + + /** + * @param string $name tag name + */ + public function removeTag(string $name): void + { + $this->deleteProperty('tags', $name); + } + + /** + * @param string $name server's property key + * @param string $value server's property value + */ + public function removeServer(string $name, $value): void + { + $this->deleteProperty('servers', $name, $value); + } + /** * @return array array of attributes default values. */ diff --git a/src/spec/Operation.php b/src/spec/Operation.php index 7bf13dd..4e9acbf 100644 --- a/src/spec/Operation.php +++ b/src/spec/Operation.php @@ -57,6 +57,41 @@ protected function attributeDefaults(): array ]; } + /** + * @param string $name tag name + */ + public function removeTag(string $name): void + { + $this->deleteProperty('tags', $name); + } + + /** + * @param string $name parameter's property key + * @param string $value parameter's property value + */ + public function removeParameter(string $name, $value): void + { + $this->deleteProperty('parameters', $name, $value); + } + + /** + * @param string $name name of security requirement + */ + public function removeSecurity(string $name): void + { + $this->deleteProperty('security', $name); + } + + /** + * @param string $name server's property key + * @param string $value server's property value + */ + public function removeServer(string $name, $value): void + { + $this->deleteProperty('servers', $name, $value); + } + + /** * Perform validation on this object, check data against OpenAPI Specification rules. * diff --git a/tests/spec/HeaderTest.php b/tests/spec/HeaderTest.php index eeced27..0977236 100644 --- a/tests/spec/HeaderTest.php +++ b/tests/spec/HeaderTest.php @@ -14,6 +14,7 @@ public function testRead() $header = Reader::readFromJson(<<assertEquals('The number of allowed requests in the current period', $header->description); $this->assertInstanceOf(\cebe\openapi\spec\Schema::class, $header->schema); $this->assertEquals('integer', $header->schema->type); + + $this->assertEquals('json', $header->style); + $header->removeProperty('style'); + $this->assertTrue(empty($header->style)); } } diff --git a/tests/spec/InfoTest.php b/tests/spec/InfoTest.php index 932e5e0..b82afaa 100644 --- a/tests/spec/InfoTest.php +++ b/tests/spec/InfoTest.php @@ -46,6 +46,10 @@ public function testRead() $this->assertInstanceOf(License::class, $info->license); $this->assertEquals('Apache 2.0', $info->license->name); $this->assertEquals('https://www.apache.org/licenses/LICENSE-2.0.html', $info->license->url); + + $this->assertNotNull($info->license); + $info->removeProperty('license'); + $this->assertTrue(empty($info->license)); } public function testReadInvalid() diff --git a/tests/spec/LinkTest.php b/tests/spec/LinkTest.php index ea373b6..9866f87 100644 --- a/tests/spec/LinkTest.php +++ b/tests/spec/LinkTest.php @@ -30,6 +30,14 @@ public function testRead() $this->assertEquals(['userId' => 'test.path.id'], $link->parameters); $this->assertEquals(null, $link->requestBody); $this->assertEquals(null, $link->server); + + $this->assertNotNull($link->parameters); + $link->removeParameter('userId'); + $this->assertTrue(empty($link->parameters['userId'])); + + $this->assertNotNull($link->parameters); + $link->removeProperty('parameters'); + $this->assertTrue(empty($link->parameters)); } public function testValidateBothOperationIdAndOperationRef() diff --git a/tests/spec/MediaTypeTest.php b/tests/spec/MediaTypeTest.php index 125e721..2a3f082 100644 --- a/tests/spec/MediaTypeTest.php +++ b/tests/spec/MediaTypeTest.php @@ -71,6 +71,10 @@ public function testRead() ]; $this->assertEquals($expectedCat, $mediaType->examples['cat']->value); + $this->assertNotNull($mediaType->examples); + $mediaType->removeExample('dog'); + $this->assertTrue(empty($mediaType->examples['dog'])); + } public function testCreateionFromObjects() diff --git a/tests/spec/OpenApiTest.php b/tests/spec/OpenApiTest.php index 20b568e..6dca0cb 100644 --- a/tests/spec/OpenApiTest.php +++ b/tests/spec/OpenApiTest.php @@ -79,6 +79,12 @@ public function testReadPetStore() // externalDocs $this->assertNull($openapi->externalDocs); + + $this->assertEquals(1, count($openapi->servers)); + $openapi->removeServer('url', 'http://petstore.swagger.io/v1'); + $this->assertEquals(1, count($openapi->servers)); + //Default only + $this->assertEquals('/', $openapi->servers[0]->url); } public function assertAllInstanceOf($className, $array) diff --git a/tests/spec/OperationTest.php b/tests/spec/OperationTest.php index 6e30566..49c4b01 100644 --- a/tests/spec/OperationTest.php +++ b/tests/spec/OperationTest.php @@ -90,5 +90,17 @@ public function testRead() // deprecated Default value is false. $this->assertFalse($operation->deprecated); + + $this->assertEquals(count($operation->tags), 1); + $operation->removeTag('pet'); + $this->assertEquals(count($operation->tags), 0); + + $this->assertTrue(!empty($operation->operationId)); + $operation->removeProperty('operationId'); + $this->assertTrue(empty($operation->operationId)); + + $this->assertEquals(count($operation->parameters), 1); + $operation->removeParameter('name', 'petId'); + $this->assertEquals(count($operation->parameters), 0); } } From cec96c7fbd03d8f18bb50d74600dc3413de63bd8 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Thu, 7 Sep 2023 11:50:38 +0100 Subject: [PATCH 4/8] Implemented methods to remove property/items --- src/SpecBaseObject.php | 2 ++ src/spec/OpenApi.php | 9 ++++----- tests/spec/OpenApiTest.php | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 45eefa7..72bfb14 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -369,6 +369,8 @@ private function _removeKey(array $arrayData, String $name, $value = null): arra unset($arrayData[$key]); }elseif($val instanceof self && !empty($val->$name) && $val->$name === $value){ unset($arrayData[$key]); + }elseif($val instanceof self && !empty($val->$name) && is_array($val->$name)){ + unset($arrayData[$key]); } } return $arrayData; diff --git a/src/spec/OpenApi.php b/src/spec/OpenApi.php index 8f2f8fe..5cf1857 100644 --- a/src/spec/OpenApi.php +++ b/src/spec/OpenApi.php @@ -45,7 +45,7 @@ protected function attributes(): array } /** - * @param string $name name of security requirement + * @param string $name name of security attribute requirement */ public function removeSecurity(string $name): void { @@ -61,12 +61,11 @@ public function removeTag(string $name): void } /** - * @param string $name server's property key - * @param string $value server's property value + * @param string $url server's url value */ - public function removeServer(string $name, $value): void + public function removeServer(string $url): void { - $this->deleteProperty('servers', $name, $value); + $this->deleteProperty('servers', 'url', $url); } /** diff --git a/tests/spec/OpenApiTest.php b/tests/spec/OpenApiTest.php index 6dca0cb..82fd7b3 100644 --- a/tests/spec/OpenApiTest.php +++ b/tests/spec/OpenApiTest.php @@ -81,7 +81,7 @@ public function testReadPetStore() $this->assertNull($openapi->externalDocs); $this->assertEquals(1, count($openapi->servers)); - $openapi->removeServer('url', 'http://petstore.swagger.io/v1'); + $openapi->removeServer('http://petstore.swagger.io/v1'); $this->assertEquals(1, count($openapi->servers)); //Default only $this->assertEquals('/', $openapi->servers[0]->url); From 5f534d46355d357088444fc89a0ae5a60d8d6608 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Thu, 7 Sep 2023 11:51:31 +0100 Subject: [PATCH 5/8] Implemented methods to remove items for Operations --- src/spec/Operation.php | 10 ++++------ tests/spec/OperationTest.php | 12 +++++++++++- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/spec/Operation.php b/src/spec/Operation.php index 4e9acbf..fe703c1 100644 --- a/src/spec/Operation.php +++ b/src/spec/Operation.php @@ -67,11 +67,10 @@ public function removeTag(string $name): void /** * @param string $name parameter's property key - * @param string $value parameter's property value */ - public function removeParameter(string $name, $value): void + public function removeParameter(string $name): void { - $this->deleteProperty('parameters', $name, $value); + $this->deleteProperty('parameters', 'name', $name); } /** @@ -84,11 +83,10 @@ public function removeSecurity(string $name): void /** * @param string $name server's property key - * @param string $value server's property value */ - public function removeServer(string $name, $value): void + public function removeServer(string $name): void { - $this->deleteProperty('servers', $name, $value); + $this->deleteProperty('servers', 'url', $name); } diff --git a/tests/spec/OperationTest.php b/tests/spec/OperationTest.php index 49c4b01..fbb1352 100644 --- a/tests/spec/OperationTest.php +++ b/tests/spec/OperationTest.php @@ -53,6 +53,8 @@ public function testRead() - petstore_auth: - write:pets - read:pets +servers: +- url: https://example.com externalDocs: description: Find more info here url: https://example.com @@ -100,7 +102,15 @@ public function testRead() $this->assertTrue(empty($operation->operationId)); $this->assertEquals(count($operation->parameters), 1); - $operation->removeParameter('name', 'petId'); + $operation->removeParameter('petId'); $this->assertEquals(count($operation->parameters), 0); + + $this->assertEquals(count($operation->servers), 1); + $operation->removeServer('https://example.com'); + $this->assertEquals(count($operation->servers), 0); + + $this->assertEquals(count($operation->security), 1); + $operation->removeSecurity('petstore_auth'); + $this->assertEquals(count($operation->security), 0); } } From c07cf0526d8a8d49430169e26ee432f0592aca53 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Thu, 7 Sep 2023 16:37:41 +0100 Subject: [PATCH 6/8] Implemented methods for removing pathItem properties --- src/spec/PathItem.php | 26 ++++++++++++++++++ tests/spec/PathTest.php | 26 ++++++++++++++++++ tests/spec/data/paths/path-item-test.yaml | 33 +++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 tests/spec/data/paths/path-item-test.yaml diff --git a/src/spec/PathItem.php b/src/spec/PathItem.php index 4b2debc..9d6e26e 100644 --- a/src/spec/PathItem.php +++ b/src/spec/PathItem.php @@ -215,4 +215,30 @@ public function setDocumentContext(SpecObjectInterface $baseDocument, JsonPointe $this->_ref->setDocumentContext($baseDocument, $jsonPointer->append('$ref')); } } + + /** + * @param string $name parameter's property key + */ + public function removeParameter(string $name): void + { + $this->deleteProperty('parameters', 'name', $name); + } + + /** + * @param string $name server's url + */ + public function removeServer(string $name): void + { + $this->deleteProperty('servers', 'url', $name); + } + + /** + * @param string $httpVerb is http verb you wish to delete. eg: get, post, etc + * @param string $operationId is unique identify of Operation + */ + public function removeOperation(string $httpVerb, $operationId): void + { + $this->deleteProperty($httpVerb, 'operationId', $operationId); + } + } diff --git a/tests/spec/PathTest.php b/tests/spec/PathTest.php index 6c46e4b..5b747a7 100644 --- a/tests/spec/PathTest.php +++ b/tests/spec/PathTest.php @@ -192,4 +192,30 @@ public function testPathItemReference() $this->assertEquals('A bar', $barPath->get->responses['200']->description); $this->assertEquals('non-existing resource', $barPath->get->responses['404']->description); } + + public function testPathItemRemoveProperties() + { + $file = __DIR__ . '/data/paths/path-item-test.yaml'; + /** @var $openapi OpenApi */ + $openapi = Reader::readFromYamlFile($file, \cebe\openapi\spec\OpenApi::class, true); + + $this->assertTrue($openapi->validate()); + $barPath = $openapi->paths['/bar']; + + $this->assertCount(2, $barPath->getOperations()); + $this->assertInstanceOf(Operation::class, $barPath->get); + $this->assertEquals('getBar', $barPath->get->operationId); + + $this->assertEquals(count($barPath->parameters), 1); + $barPath->removeParameter('id'); + $this->assertEquals(count($barPath->parameters), 0); + + $barPath->removeOperation('get', 'getBar'); + $this->assertCount(1, $barPath->getOperations()); + + $this->assertInstanceOf(Operation::class, $barPath->post); + $this->assertEquals('createBar', $barPath->post->operationId); + $barPath->removeOperation('post', 'createBar'); + $this->assertEmpty($barPath->getOperations()); + } } diff --git a/tests/spec/data/paths/path-item-test.yaml b/tests/spec/data/paths/path-item-test.yaml new file mode 100644 index 0000000..6a93299 --- /dev/null +++ b/tests/spec/data/paths/path-item-test.yaml @@ -0,0 +1,33 @@ +openapi: 3.0.2 +info: + title: My API + version: 1.0.0 +x-extension-1: Extension1 +x-extension-2: Extension2 +X-EXTENSION: Invalid because of Uppercase X- +xyz-extension: invalid extension +paths: + /bar: + parameters: + - name: id + in: path + description: ID of the item. + required: true + get: + operationId: getBar + responses: + '200': + $ref: 'openapi.yaml#/components/responses/Bar' + post: + operationId: createBar + responses: + '200': + $ref: 'openapi.yaml#/components/responses/Bar' +components: + responses: + Bar: + description: A bar + content: + application/json: + schema: { type: object } + \ No newline at end of file From 958a118518885dc2d71175156e6f009148dfe673 Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Thu, 7 Sep 2023 16:38:08 +0100 Subject: [PATCH 7/8] Implemented methods for removing response properties --- src/spec/Response.php | 24 ++++++++++++++++++++++++ tests/spec/ResponseTest.php | 28 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/spec/Response.php b/src/spec/Response.php index 459ad14..6866f15 100644 --- a/src/spec/Response.php +++ b/src/spec/Response.php @@ -34,6 +34,30 @@ protected function attributes(): array ]; } + /** + * @param string $name headers' name + */ + public function removeHeader(string $name): void + { + $this->deleteProperty('headers', $name); + } + + /** + * @param string $operationId headers' operationId + */ + public function removeLinkByOperationId(string $operationId): void + { + $this->deleteProperty('links', 'operationId', $operationId); + } + + /** + * @param string $operationRef link's operationRef + */ + public function removeLinkByoperationRef(string $operationRef): void + { + $this->deleteProperty('links', 'operationRef', $operationRef); + } + /** * Perform validation on this object, check data against OpenAPI Specification rules. */ diff --git a/tests/spec/ResponseTest.php b/tests/spec/ResponseTest.php index d11b8e2..9aca9f3 100644 --- a/tests/spec/ResponseTest.php +++ b/tests/spec/ResponseTest.php @@ -68,6 +68,20 @@ public function testResponses() /** @var $responses Responses */ $responses = Reader::readFromYaml(<<<'YAML' '200': + headers: + X-RateLimit-Limit: + schema: + type: integer + description: Request limit per hour. + X-RateLimit-Remaining: + schema: + type: integer + description: The number of requests left for the time window. + links: + GetUserByUserId: + operationId: getUser + GetUserByUserRef: + operationRef: '/paths/1/get' description: a pet to be returned content: application/json: @@ -121,6 +135,20 @@ public function testResponses() $this->assertInstanceOf(Response::class, $response); } $this->assertEquals([200, 'default'], $keys); + + //Test Remove headers + $response = $responses['200']; + $this->assertEquals(count($response->headers), 2); + $response->removeHeader('X-RateLimit-Limit'); + $this->assertEquals(count($response->headers), 1); + + //Test Remove links + $this->assertEquals(count($response->links), 2); + $response->removeLinkByOperationId('getUser'); + $this->assertEquals(count($response->links), 1); + + $response->removeLinkByoperationRef('/paths/1/get'); + $this->assertEquals(count($response->links), 0); } public function testResponseCodes() From a3b0cacfc4668eb8585011c13b84d57158c67b5b Mon Sep 17 00:00:00 2001 From: Arinzechukwu Date: Fri, 8 Sep 2023 14:15:19 +0100 Subject: [PATCH 8/8] Fixed coding styles --- src/SpecBaseObject.php | 26 ++++++++++++++------------ src/spec/Link.php | 2 +- src/spec/MediaType.php | 4 ++-- src/spec/OAuthFlow.php | 2 +- src/spec/OpenApi.php | 6 +++--- src/spec/Operation.php | 10 +++++----- src/spec/PathItem.php | 8 ++++---- src/spec/Response.php | 6 +++--- 8 files changed, 33 insertions(+), 31 deletions(-) diff --git a/src/SpecBaseObject.php b/src/SpecBaseObject.php index 72bfb14..7a8812e 100644 --- a/src/SpecBaseObject.php +++ b/src/SpecBaseObject.php @@ -353,24 +353,25 @@ protected function deleteProperty($key, $name = null, $value = null): void { if(is_array($this->$key) && $name) { $this->_properties[$key] = $this->_removeKey($this->$key, $name, $value); - }else{ - $this->_properties = $this->_removeKey($this->_properties, $key); + } else { + $this->_properties = $this->_removeKey($this->_properties, $key); } } - private function _removeKey(array $arrayData, String $name, $value = null): array { + private function _removeKey(array $arrayData, String $name, $value = null): array + { if(!empty($arrayData[$name])) { $properties = $arrayData; unset($properties[$name]); return $properties; } - foreach($arrayData as $key => $val){ - if($name === $val){ - unset($arrayData[$key]); - }elseif($val instanceof self && !empty($val->$name) && $val->$name === $value){ - unset($arrayData[$key]); - }elseif($val instanceof self && !empty($val->$name) && is_array($val->$name)){ - unset($arrayData[$key]); + foreach($arrayData as $key => $val) { + if($name === $val) { + unset($arrayData[$key]); + } elseif($val instanceof self && !empty($val->$name) && $val->$name === $value) { + unset($arrayData[$key]); + } elseif($val instanceof self && !empty($val->$name) && is_array($val->$name)) { + unset($arrayData[$key]); } } return $arrayData; @@ -558,7 +559,8 @@ public function getExtensions(): array * Remove a property or an attribute * @param string $name name of property to be removed */ - public function removeProperty($name){ + public function removeProperty($name) + { $this->deleteProperty($name); - } + } } diff --git a/src/spec/Link.php b/src/spec/Link.php index ffffe8d..a39c521 100644 --- a/src/spec/Link.php +++ b/src/spec/Link.php @@ -55,5 +55,5 @@ protected function performValidation() public function removeParameter(string $name): void { $this->deleteProperty('parameters', $name); - } + } } diff --git a/src/spec/MediaType.php b/src/spec/MediaType.php index 4df3db2..af5e6d6 100644 --- a/src/spec/MediaType.php +++ b/src/spec/MediaType.php @@ -78,7 +78,7 @@ public function __construct(array $data) public function removeExample(string $name): void { $this->deleteProperty('examples', $name); - } + } /** * @param string $name example name @@ -86,7 +86,7 @@ public function removeExample(string $name): void public function removeEncoding(string $name): void { $this->deleteProperty('encoding', $name); - } + } /** * Perform validation on this object, check data against OpenAPI Specification rules. diff --git a/src/spec/OAuthFlow.php b/src/spec/OAuthFlow.php index d6e1737..88a5321 100644 --- a/src/spec/OAuthFlow.php +++ b/src/spec/OAuthFlow.php @@ -40,7 +40,7 @@ protected function attributes(): array public function removeScope(string $name): void { $this->deleteProperty('scopes', $name); - } + } /** * Perform validation on this object, check data against OpenAPI Specification rules. diff --git a/src/spec/OpenApi.php b/src/spec/OpenApi.php index 5cf1857..0f7c05b 100644 --- a/src/spec/OpenApi.php +++ b/src/spec/OpenApi.php @@ -50,7 +50,7 @@ protected function attributes(): array public function removeSecurity(string $name): void { $this->deleteProperty('security', $name); - } + } /** * @param string $name tag name @@ -58,7 +58,7 @@ public function removeSecurity(string $name): void public function removeTag(string $name): void { $this->deleteProperty('tags', $name); - } + } /** * @param string $url server's url value @@ -66,7 +66,7 @@ public function removeTag(string $name): void public function removeServer(string $url): void { $this->deleteProperty('servers', 'url', $url); - } + } /** * @return array array of attributes default values. diff --git a/src/spec/Operation.php b/src/spec/Operation.php index fe703c1..295da21 100644 --- a/src/spec/Operation.php +++ b/src/spec/Operation.php @@ -57,13 +57,13 @@ protected function attributeDefaults(): array ]; } - /** + /** * @param string $name tag name */ public function removeTag(string $name): void { $this->deleteProperty('tags', $name); - } + } /** * @param string $name parameter's property key @@ -71,7 +71,7 @@ public function removeTag(string $name): void public function removeParameter(string $name): void { $this->deleteProperty('parameters', 'name', $name); - } + } /** * @param string $name name of security requirement @@ -79,7 +79,7 @@ public function removeParameter(string $name): void public function removeSecurity(string $name): void { $this->deleteProperty('security', $name); - } + } /** * @param string $name server's property key @@ -87,7 +87,7 @@ public function removeSecurity(string $name): void public function removeServer(string $name): void { $this->deleteProperty('servers', 'url', $name); - } + } /** diff --git a/src/spec/PathItem.php b/src/spec/PathItem.php index 9d6e26e..f0f2337 100644 --- a/src/spec/PathItem.php +++ b/src/spec/PathItem.php @@ -222,7 +222,7 @@ public function setDocumentContext(SpecObjectInterface $baseDocument, JsonPointe public function removeParameter(string $name): void { $this->deleteProperty('parameters', 'name', $name); - } + } /** * @param string $name server's url @@ -233,12 +233,12 @@ public function removeServer(string $name): void } /** - * @param string $httpVerb is http verb you wish to delete. eg: get, post, etc + * @param string $httpVerb is http verb you wish to delete. eg: get, post, etc * @param string $operationId is unique identify of Operation */ public function removeOperation(string $httpVerb, $operationId): void { $this->deleteProperty($httpVerb, 'operationId', $operationId); - } - + } + } diff --git a/src/spec/Response.php b/src/spec/Response.php index 6866f15..27721ac 100644 --- a/src/spec/Response.php +++ b/src/spec/Response.php @@ -40,7 +40,7 @@ protected function attributes(): array public function removeHeader(string $name): void { $this->deleteProperty('headers', $name); - } + } /** * @param string $operationId headers' operationId @@ -48,7 +48,7 @@ public function removeHeader(string $name): void public function removeLinkByOperationId(string $operationId): void { $this->deleteProperty('links', 'operationId', $operationId); - } + } /** * @param string $operationRef link's operationRef @@ -56,7 +56,7 @@ public function removeLinkByOperationId(string $operationId): void public function removeLinkByoperationRef(string $operationRef): void { $this->deleteProperty('links', 'operationRef', $operationRef); - } + } /** * Perform validation on this object, check data against OpenAPI Specification rules.