From 534d2fbeb1b271806c31d9e67b348df0473b09bf Mon Sep 17 00:00:00 2001 From: Christian Lopez Espinola Date: Wed, 27 May 2026 17:57:12 +0200 Subject: [PATCH 1/2] fix: allow "#", "?", and "?#" as valid URI references per RFC 3986 These are valid relative-references: path-empty + fragment/query. The RFC grammar explicitly allows zero-length paths, queries, and fragments via the "*" (zero-or-more) quantifier. Fixes #909 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Tool/Validator/RelativeReferenceValidator.php | 8 -------- tests/Tool/Validator/RelativeReferenceValidatorTest.php | 8 +++++--- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php b/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php index fd95f7bf..79fede0d 100644 --- a/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php +++ b/src/JsonSchema/Tool/Validator/RelativeReferenceValidator.php @@ -44,14 +44,6 @@ public static function isValid(string $ref): bool return false; // Spaces are not allowed in URIs } - if (preg_match('/^\?#|^#$/', $ref)) { - return false; // Missing path but having query and fragment - } - - if ($ref === '#' || $ref === '?') { - return false; // Missing path and having only fragment or query - } - return true; } } diff --git a/tests/Tool/Validator/RelativeReferenceValidatorTest.php b/tests/Tool/Validator/RelativeReferenceValidatorTest.php index 7b46e232..762daa3a 100644 --- a/tests/Tool/Validator/RelativeReferenceValidatorTest.php +++ b/tests/Tool/Validator/RelativeReferenceValidatorTest.php @@ -26,6 +26,11 @@ public function validRelativeReferenceDataProvider(): \Generator yield 'Relative path from root' => ['ref' => '/relative/path']; yield 'Relative path up one level' => ['ref' => '../up-one-level']; yield 'Relative path from current' => ['ref' => 'foo/bar']; + yield 'Empty fragment (RFC 3986: path-empty + fragment)' => ['ref' => '#']; + yield 'Fragment only' => ['ref' => '#section']; + yield 'Empty query (RFC 3986: path-empty + query)' => ['ref' => '?']; + yield 'Empty query and empty fragment' => ['ref' => '?#']; + yield 'Query and fragment' => ['ref' => '?query#fragment']; } public function invalidRelativeReferenceDataProvider(): \Generator @@ -33,8 +38,5 @@ public function invalidRelativeReferenceDataProvider(): \Generator yield 'Absolute URI' => ['ref' => 'http://example.com']; yield 'Three slashes' => ['ref' => '///three/slashes']; yield 'Path with spaces' => ['ref' => '/path with spaces']; - yield 'No path having query and fragment' => ['ref' => '?#invalid']; - yield 'Missing path having fragment' => ['ref' => '#']; - yield 'Missing path having query' => ['ref' => '?']; } } From c8c49b4530bddf922a37b4c424a5c294048c2860 Mon Sep 17 00:00:00 2001 From: Danny van der Sluijs Date: Wed, 27 May 2026 21:28:27 +0200 Subject: [PATCH 2/2] Include test case for empty query and fragment Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- tests/Tool/Validator/RelativeReferenceValidatorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Tool/Validator/RelativeReferenceValidatorTest.php b/tests/Tool/Validator/RelativeReferenceValidatorTest.php index 762daa3a..9894e682 100644 --- a/tests/Tool/Validator/RelativeReferenceValidatorTest.php +++ b/tests/Tool/Validator/RelativeReferenceValidatorTest.php @@ -30,6 +30,7 @@ public function validRelativeReferenceDataProvider(): \Generator yield 'Fragment only' => ['ref' => '#section']; yield 'Empty query (RFC 3986: path-empty + query)' => ['ref' => '?']; yield 'Empty query and empty fragment' => ['ref' => '?#']; + yield 'Empty query and fragment' => ['ref' => '?#fragment']; yield 'Query and fragment' => ['ref' => '?query#fragment']; }