From 9d0921e709dce668b1f054caef2fec65c2ca4bf0 Mon Sep 17 00:00:00 2001 From: Erayd Date: Fri, 17 Mar 2017 17:06:44 +1300 Subject: [PATCH] [BUGFIX] Add provided schema under a dummy / internal URI (fixes #376) (#378) * Add provided schema under a dummy / internal URI (fixes #376) In order to resolve internal $ref references within a user-provided schema, SchemaStorage needs to know about the schema. As user-supplied schemas do not have an associated URI, use a dummy / internal one instead. * Remove dangling use * Change URI to class constant on SchemaStorage --- src/JsonSchema/SchemaStorage.php | 7 ++++++- src/JsonSchema/Validator.php | 4 ++++ tests/SchemaStorageTest.php | 10 ++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/JsonSchema/SchemaStorage.php b/src/JsonSchema/SchemaStorage.php index 6450572e..55d7985a 100644 --- a/src/JsonSchema/SchemaStorage.php +++ b/src/JsonSchema/SchemaStorage.php @@ -10,6 +10,8 @@ class SchemaStorage implements SchemaStorageInterface { + const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema'; + protected $uriRetriever; protected $uriResolver; protected $schemas = array(); @@ -43,7 +45,10 @@ public function getUriResolver() */ public function addSchema($id, $schema = null) { - if (is_null($schema)) { + if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) { + // if the schema was user-provided to Validator and is still null, then assume this is + // what the user intended, as there's no way for us to retrieve anything else. User-supplied + // schemas do not have an associated URI when passed via Validator::validate(). $schema = $this->uriRetriever->retrieve($id); } $objectIterator = new ObjectIterator($schema); diff --git a/src/JsonSchema/Validator.php b/src/JsonSchema/Validator.php index e2a919bc..9f44e512 100644 --- a/src/JsonSchema/Validator.php +++ b/src/JsonSchema/Validator.php @@ -12,6 +12,7 @@ use JsonSchema\Constraints\BaseConstraint; use JsonSchema\Constraints\Constraint; use JsonSchema\Exception\InvalidConfigException; +use JsonSchema\SchemaStorage; /** * A JsonSchema Constraint @@ -41,6 +42,9 @@ public function validate(&$value, $schema = null, $checkMode = null) $this->factory->setConfig($checkMode); } + // add provided schema to SchemaStorage with internal URI to allow internal $ref resolution + $this->factory->getSchemaStorage()->addSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI, $schema); + $validator = $this->factory->createInstanceFor('schema'); $validator->check($value, $schema); diff --git a/tests/SchemaStorageTest.php b/tests/SchemaStorageTest.php index c3388bf4..92e1d5c3 100644 --- a/tests/SchemaStorageTest.php +++ b/tests/SchemaStorageTest.php @@ -11,6 +11,7 @@ use JsonSchema\SchemaStorage; use JsonSchema\Uri\UriRetriever; +use JsonSchema\Validator; use Prophecy\Argument; class SchemaStorageTest extends \PHPUnit_Framework_TestCase @@ -31,6 +32,15 @@ public function testResolveRef() ); } + public function testResolveTopRef() + { + $input = json_decode('{"propertyOne":"notANumber"}'); + $schema = json_decode('{"$ref":"#/definition","definition":{"properties":{"propertyOne":{"type":"number"}}}}'); + $v = new Validator(); + $v->validate($input, $schema); + $this->assertFalse($v->isValid()); + } + /** * @depends testResolveRef */