diff --git a/src/Path/PointerUtil.php b/src/Path/PointerUtil.php index 1062f6d..cb8accb 100644 --- a/src/Path/PointerUtil.php +++ b/src/Path/PointerUtil.php @@ -37,14 +37,22 @@ public static function getSchemaPointers($path, $isURIFragmentId = false) $parts = explode(':', $item); if (isset($parts[0])) { $schemaPaths = explode('[', $parts[0], 2); + if (isset($schemaPaths[1])) { + $schemaPaths[1] = substr(strtr($schemaPaths[1], array('~1' => '~', '~2' => ':')), 0, -1); + } + if ($schemaPaths[0] === Schema::PROP_REF) { $result[] = $pointer . '/' . JsonPointer::escapeSegment(Schema::PROP_REF, $isURIFragmentId); - $pointer = self::rebuildPointer(substr($schemaPaths[1], 0, -1), $isURIFragmentId); + if (strpos($schemaPaths[1], '://')) { + $pointer = $schemaPaths[1]; + } else { + $pointer = self::rebuildPointer($schemaPaths[1], $isURIFragmentId); + } continue; } $pointer .= '/' . JsonPointer::escapeSegment($schemaPaths[0], $isURIFragmentId); if (isset($schemaPaths[1])) { - $pointer .= '/' . JsonPointer::escapeSegment(substr($schemaPaths[1], 0, -1), $isURIFragmentId); + $pointer .= '/' . JsonPointer::escapeSegment($schemaPaths[1], $isURIFragmentId); } elseif ($parts[1]) { $pointer .= '/' . JsonPointer::escapeSegment($parts[1], $isURIFragmentId); } diff --git a/src/Schema.php b/src/Schema.php index 5a16f22..29091d6 100644 --- a/src/Schema.php +++ b/src/Schema.php @@ -815,7 +815,7 @@ private function processObject($data, Context $options, $path, $result = null) if (preg_match(Helper::toPregPattern($pattern), $key)) { $found = true; $value = self::unboolSchema($propertySchema)->process($value, $options, - $path . '->patternProperties[' . $pattern . ']:' . $key); + $path . '->patternProperties[' . strtr($pattern, array('~' => '~1', ':' => '~2')) . ']:' . $key); if (!$options->validateOnly && $import) { $result->addPatternPropertyName($pattern, $key); } @@ -988,7 +988,7 @@ public function process($data, Context $options, $path = '#', $result = null) $import = $options->import; if ($ref = $this->getFromRef()) { - $path .= '->$ref[' . $ref . ']'; + $path .= '->$ref[' . strtr($ref, array('~' => '~1', ':' => '~2')) . ']'; } if (!$import && $data instanceof ObjectItemContract) { diff --git a/tests/src/PHPUnit/Ref/FileResolverTest.php b/tests/src/PHPUnit/Ref/FileResolverTest.php new file mode 100644 index 0000000..30ff76b --- /dev/null +++ b/tests/src/PHPUnit/Ref/FileResolverTest.php @@ -0,0 +1,70 @@ +setSchemaData( + 'file://baseTypes.json', + json_decode(<<<'JSON' +{ + "stringFromOutside": { + "type": "string" + } +} +JSON +) + ); + + $schemaData = json_decode(<<<'JSON' +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "properties": { + "sample": { "$ref": "file://baseTypes.json#/stringFromOutside" } + }, + "required": ["sample"], + "additionalProperties": false +} +JSON +); + $options = new Context(); + $options->remoteRefProvider = $refProvider; + $schema = Schema::import($schemaData, $options); + + $schema->in(json_decode('{"sample": "some-string"}')); // no exception for string + try { + $schema->in(json_decode('{"sample": 1}')); // exception for int + $this->fail('Exception expected'); + } catch (InvalidValue $exception) { + $expected = <<<'TEXT' +Swaggest\JsonSchema\Exception\Error Object +( + [error] => String expected, 1 received + [schemaPointers] => Array + ( + [0] => /properties/sample/$ref + [1] => file://baseTypes.json#/stringFromOutside + ) + + [dataPointer] => /sample + [processingPath] => #->properties:sample->$ref[file~2//baseTypes.json#/stringFromOutside] + [subErrors] => +) + +TEXT; + + $this->assertSame($expected, print_r($exception->inspect(), 1)); + } + } + +} \ No newline at end of file