From b42e5bfe5e07f424b2e3ad64ebae550718cc92ea Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:17:45 +0100 Subject: [PATCH 01/10] Summary and description support for references --- Makefile | 2 +- src/json/JsonReference.php | 30 +++++++++++++++++++--- src/spec/Reference.php | 50 +++++++++++++++++++++++++++++++----- tests/spec/ReferenceTest.php | 45 ++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 421c5711..899a04b8 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ install: composer.lock yarn.lock test: unit test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json unit: - $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --verbose --colors=always $(TESTCASE) + $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --colors=always $(TESTCASE) test-debug: unit-debug test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index 5f248881..96290c64 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -28,6 +28,14 @@ final class JsonReference implements JsonSerializable * @var JsonPointer */ private $_pointer; + /** + * @var string|null + */ + private $_summary; + /** + * @var string|null + */ + private $_description; /** * Create a JSON Reference instance from a JSON document. @@ -42,7 +50,11 @@ public static function createFromJson(string $json): JsonReference if (!isset($refObject['$ref'])) { throw new MalformedJsonReferenceObjectException('JSON Reference Object must contain the "$ref" member.'); } - return static::createFromReference($refObject['$ref']); + return static::createFromReference( + $refObject['$ref'], + $refObject['summary'] ?? null, + $refObject['description'] ?? null, + ); } /** @@ -66,10 +78,16 @@ public static function createFromUri(string $uri, ?JsonPointer $jsonPointer = nu * @return JsonReference * @throws InvalidJsonPointerSyntaxException if an invalid JSON pointer string is passed as part of the fragment section. */ - public static function createFromReference(string $referenceURI): JsonReference + public static function createFromReference( + string $referenceURI, + ?string $summary = null, + ?string $description = null, + ): JsonReference { $jsonReference = new JsonReference(); - if (strpos($referenceURI, '#') !== false) { + $jsonReference->_summary = $summary; + $jsonReference->_description = $description; + if (str_contains($referenceURI, '#')) { list($uri, $fragment) = explode('#', $referenceURI, 2); $jsonReference->_uri = $uri; $jsonReference->_pointer = new JsonPointer(rawurldecode($fragment)); @@ -129,6 +147,10 @@ public function getReference(): string #[\ReturnTypeWillChange] public function jsonSerialize() //: mixed { - return (object)['$ref' => $this->getReference()]; + return (object) array_filter([ + '$ref' => $this->getReference(), + 'summary' => $this->_summary, + 'description' => $this->_description, + ]); } } diff --git a/src/spec/Reference.php b/src/spec/Reference.php index 81f07e87..428bdfbf 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -8,7 +8,6 @@ namespace cebe\openapi\spec; use cebe\openapi\DocumentContextInterface; -use cebe\openapi\exceptions\IOException; use cebe\openapi\exceptions\TypeErrorException; use cebe\openapi\exceptions\UnresolvableReferenceException; use cebe\openapi\json\InvalidJsonPointerSyntaxException; @@ -17,7 +16,6 @@ use cebe\openapi\json\NonexistentJsonPointerReferenceException; use cebe\openapi\ReferenceContext; use cebe\openapi\SpecObjectInterface; -use Symfony\Component\Yaml\Yaml; /** * Reference Object @@ -37,6 +35,14 @@ class Reference implements SpecObjectInterface, DocumentContextInterface * @var string */ private $_ref; + /** + * @var string|null + */ + private $_summary; + /** + * @var string|null + */ + private $_description; /** * @var JsonReference|null */ @@ -81,15 +87,33 @@ public function __construct(array $data, ?string $to = null) 'Unable to instantiate Reference Object, value of $ref must be a string.' ); } + if (isset($data['summary']) && !is_string($data['summary'])) { + throw new TypeErrorException( + 'Unable to instantiate Reference Object, value of summary must be a string.' + ); + } + if (isset($data['description']) && !is_string($data['description'])) { + throw new TypeErrorException( + 'Unable to instantiate Reference Object, value of description must be a string.' + ); + } + $this->_to = $to; $this->_ref = $data['$ref']; + $this->_summary = $data['summary'] ?? null; + $this->_description = $data['description'] ?? null; try { - $this->_jsonReference = JsonReference::createFromReference($this->_ref); + $this->_jsonReference = JsonReference::createFromReference( + $this->_ref, + $this->_summary, + $this->_description + ); } catch (InvalidJsonPointerSyntaxException $e) { $this->_errors[] = 'Reference: value of $ref is not a valid JSON pointer: ' . $e->getMessage(); } - if (count($data) !== 1) { - $this->_errors[] = 'Reference: additional properties are given. Only $ref should be set in a Reference Object.'; + + if (!empty(array_diff(array_keys($data), ['$ref', 'summary', 'description']))) { + $this->_errors[] = 'Reference: additional properties are given. Only $ref, summary and description should be set in a Reference Object.'; } } @@ -99,7 +123,11 @@ public function __construct(array $data, ?string $to = null) */ public function getSerializableData() { - return (object) ['$ref' => $this->_ref]; + return (object) array_filter([ + '$ref' => $this->_ref, + 'summary' => $this->_summary, + 'description' => $this->_description, + ]); } /** @@ -135,6 +163,16 @@ public function getReference() return $this->_ref; } + public function getSummary() + { + return $this->_summary; + } + + public function getDescription() + { + return $this->_description; + } + /** * @return JsonReference the JSON Reference. */ diff --git a/tests/spec/ReferenceTest.php b/tests/spec/ReferenceTest.php index b94c946e..6ee6c939 100644 --- a/tests/spec/ReferenceTest.php +++ b/tests/spec/ReferenceTest.php @@ -657,4 +657,49 @@ public function testResolveRelativePathAll() } } + public function testReferenceExtraFields() + { + /** @var $openapi OpenApi */ + $openapi = Reader::readFromYaml(<<<'YAML' +openapi: 3.1.0 +info: + title: test api + version: 1.0.0 +components: + schemas: + Pet: + type: object + properties: + id: + type: integer +paths: + '/pet': + get: + responses: + 200: + description: return a pet + content: + 'application/json': + schema: + $ref: "#/components/schemas/Pet" + summary: 'Pet Schema' + description: 'This is a pet schema' +YAML + , OpenApi::class); + + $result = $openapi->validate(); + $this->assertEquals([], $openapi->getErrors()); + $this->assertTrue($result); + + /** @var $petResponse Response */ + $petResponse = $openapi->paths->getPath('/pet')->get->responses['200']; + $this->assertInstanceOf(Reference::class, $ref = $petResponse->content['application/json']->schema); + $this->assertEquals('Pet Schema', $ref->getSummary()); + $this->assertEquals('This is a pet schema', $ref->getDescription()); + + $openapi->resolveReferences(new \cebe\openapi\ReferenceContext($openapi, 'file:///tmp/openapi.yaml')); + + $this->assertInstanceOf(Schema::class, $refSchema = $petResponse->content['application/json']->schema); + $this->assertSame($openapi->components->schemas['Pet'], $refSchema); + } } From acb1268625ed6a6955ef20540c18726e2f2b9fb9 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:18:58 +0100 Subject: [PATCH 02/10] Summary and description support for references --- .github/workflows/php.yml | 4 ++-- Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 81ca1eff..6be43e60 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -93,7 +93,7 @@ jobs: - name: Require newer phpunit/phpunit version run: "composer require phpunit/phpunit '^11.4' --dev --no-interaction --ansi --no-install" - if: matrix.php == '8.3' + if: matrix.php >= '8.3' - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v2" @@ -109,7 +109,7 @@ jobs: - name: PHPUnit tests run: make test-debug - if: matrix.php == '8.3' + if: matrix.php >= '8.3' - name: Code coverage run: make coverage diff --git a/Makefile b/Makefile index 899a04b8..421c5711 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ install: composer.lock yarn.lock test: unit test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json unit: - $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --colors=always $(TESTCASE) + $(DOCKER_PHP) php $(PHPARGS) $(XPHPARGS) vendor/bin/phpunit --verbose --colors=always $(TESTCASE) test-debug: unit-debug test-recursion.json test-recursion2.yaml test-recursion3_index.yaml test-empty-maps.json From 20533635d184ee4a8f86f44ee17a7477cf0989d3 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:20:36 +0100 Subject: [PATCH 03/10] Summary and description support for references --- src/spec/Reference.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/spec/Reference.php b/src/spec/Reference.php index 428bdfbf..e784af75 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -163,11 +163,17 @@ public function getReference() return $this->_ref; } + /** + * @return string|null + */ public function getSummary() { return $this->_summary; } + /** + * @return string|null + */ public function getDescription() { return $this->_description; From 819971efdbe8fd23225ff8fce0e139675de47a50 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:24:06 +0100 Subject: [PATCH 04/10] Summary and description support for references --- src/json/JsonReference.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index 96290c64..489b3bde 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -52,8 +52,8 @@ public static function createFromJson(string $json): JsonReference } return static::createFromReference( $refObject['$ref'], - $refObject['summary'] ?? null, - $refObject['description'] ?? null, + isset($refObject['summary']) ? $refObject['summary'] : null, + isset($refObject['description']) ? $refObject['description'] : null, ); } From 2591e51fd206569bb6ba156783b4b52775109a16 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:39:20 +0100 Subject: [PATCH 05/10] Summary and description support for references --- src/json/JsonReference.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index 489b3bde..b74095c9 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -80,8 +80,8 @@ public static function createFromUri(string $uri, ?JsonPointer $jsonPointer = nu */ public static function createFromReference( string $referenceURI, - ?string $summary = null, - ?string $description = null, + string $summary = null, + string $description = null, ): JsonReference { $jsonReference = new JsonReference(); From b8fb2ceca2a5c636cef9fffbb065de7b02173b01 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:47:08 +0100 Subject: [PATCH 06/10] Summary and description support for references --- src/json/JsonReference.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index b74095c9..a8e4e138 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -80,8 +80,8 @@ public static function createFromUri(string $uri, ?JsonPointer $jsonPointer = nu */ public static function createFromReference( string $referenceURI, - string $summary = null, - string $description = null, + ?string $summary = null, + ?string $description = null ): JsonReference { $jsonReference = new JsonReference(); From 4c4f9701334801b6cbe8d1f67d354b86d3c1cc4b Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 16:52:56 +0100 Subject: [PATCH 07/10] Summary and description support for references --- src/json/JsonReference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index a8e4e138..dfb07d93 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -53,7 +53,7 @@ public static function createFromJson(string $json): JsonReference return static::createFromReference( $refObject['$ref'], isset($refObject['summary']) ? $refObject['summary'] : null, - isset($refObject['description']) ? $refObject['description'] : null, + isset($refObject['description']) ? $refObject['description'] : null ); } From ea0bd1a33df3ff795e8bc52830d94accf2633ee7 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 17:13:56 +0100 Subject: [PATCH 08/10] Summary and description support for references --- src/json/JsonReference.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index dfb07d93..898090e5 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -87,7 +87,7 @@ public static function createFromReference( $jsonReference = new JsonReference(); $jsonReference->_summary = $summary; $jsonReference->_description = $description; - if (str_contains($referenceURI, '#')) { + if (strpos($referenceURI, '#') !== false) { list($uri, $fragment) = explode('#', $referenceURI, 2); $jsonReference->_uri = $uri; $jsonReference->_pointer = new JsonPointer(rawurldecode($fragment)); From 64a99456026eee76c72dc5cca80ae1ce86b337e6 Mon Sep 17 00:00:00 2001 From: hotrush Date: Fri, 10 Jan 2025 17:19:28 +0100 Subject: [PATCH 09/10] Summary and description support for references --- src/json/JsonReference.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/json/JsonReference.php b/src/json/JsonReference.php index 898090e5..113cd1ec 100644 --- a/src/json/JsonReference.php +++ b/src/json/JsonReference.php @@ -82,8 +82,7 @@ public static function createFromReference( string $referenceURI, ?string $summary = null, ?string $description = null - ): JsonReference - { + ): JsonReference { $jsonReference = new JsonReference(); $jsonReference->_summary = $summary; $jsonReference->_description = $description; From b8c14b1d7802a4a81e15ca1160d9b0dbe21d2090 Mon Sep 17 00:00:00 2001 From: hotrush Date: Thu, 16 Jan 2025 11:37:46 +0100 Subject: [PATCH 10/10] Return back schemas folder to the package --- .gitattributes | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 031e7ed3..1281f04c 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,4 @@ /.github export-ignore -/schemas export-ignore /tests export-ignore .gitattributes export-ignore .gitignore export-ignore