From 549b4afc4e140350a3da10b87719d26dfbeecf83 Mon Sep 17 00:00:00 2001 From: Erayd Date: Sat, 6 May 2017 02:28:45 +1200 Subject: [PATCH] [BUGFIX] Cast empty schema arrays to object (#409) * Cast root to object * Use function_exists to allow polyfill compatibility * Move array->object conversion to SchemaConstraint & SchemaStorage Fixes issue #408 --- src/JsonSchema/Constraints/BaseConstraint.php | 4 ++-- src/JsonSchema/Constraints/SchemaConstraint.php | 11 ++++++----- src/JsonSchema/SchemaStorage.php | 7 +++++++ src/JsonSchema/Validator.php | 10 ++++------ 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/JsonSchema/Constraints/BaseConstraint.php b/src/JsonSchema/Constraints/BaseConstraint.php index a473edac..13168d71 100644 --- a/src/JsonSchema/Constraints/BaseConstraint.php +++ b/src/JsonSchema/Constraints/BaseConstraint.php @@ -146,12 +146,12 @@ public static function arrayToObjectRecursive($array) $json = json_encode($array); if (json_last_error() !== \JSON_ERROR_NONE) { $message = 'Unable to encode schema array as JSON'; - if (version_compare(phpversion(), '5.5.0', '>=')) { + if (function_exists('json_last_error_msg')) { $message .= ': ' . json_last_error_msg(); } throw new InvalidArgumentException($message); } - return json_decode($json); + return (object) json_decode($json); } } diff --git a/src/JsonSchema/Constraints/SchemaConstraint.php b/src/JsonSchema/Constraints/SchemaConstraint.php index fad577b7..8218d256 100644 --- a/src/JsonSchema/Constraints/SchemaConstraint.php +++ b/src/JsonSchema/Constraints/SchemaConstraint.php @@ -36,16 +36,17 @@ public function check(&$element, $schema = null, JsonPointer $path = null, $i = // passed schema $validationSchema = $schema; } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) { - $inlineSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty); - if (is_array($inlineSchema)) { - $inlineSchema = json_decode(json_encode($inlineSchema)); - } // inline schema - $validationSchema = $inlineSchema; + $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty); } else { throw new InvalidArgumentException('no schema found to verify against'); } + // cast array schemas to object + if (is_array($validationSchema)) { + $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema); + } + // validate schema against whatever is defined in $validationSchema->$schema. If no // schema is defined, assume self::DEFAULT_SCHEMA_SPEC (currently draft-04). if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) { diff --git a/src/JsonSchema/SchemaStorage.php b/src/JsonSchema/SchemaStorage.php index 3ee081e3..3c17c8c4 100644 --- a/src/JsonSchema/SchemaStorage.php +++ b/src/JsonSchema/SchemaStorage.php @@ -2,6 +2,7 @@ namespace JsonSchema; +use JsonSchema\Constraints\BaseConstraint; use JsonSchema\Entity\JsonPointer; use JsonSchema\Exception\UnresolvableJsonPointerException; use JsonSchema\Iterator\ObjectIterator; @@ -51,6 +52,12 @@ public function addSchema($id, $schema = null) // schemas do not have an associated URI when passed via Validator::validate(). $schema = $this->uriRetriever->retrieve($id); } + + // cast array schemas to object + if (is_array($schema)) { + $schema = BaseConstraint::arrayToObjectRecursive($schema); + } + $objectIterator = new ObjectIterator($schema); foreach ($objectIterator as $toResolveSchema) { if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) { diff --git a/src/JsonSchema/Validator.php b/src/JsonSchema/Validator.php index 49fec4c1..8d1b50c9 100644 --- a/src/JsonSchema/Validator.php +++ b/src/JsonSchema/Validator.php @@ -45,11 +45,6 @@ public function validate(&$value, $schema = null, $checkMode = null) // reset errors prior to validation $this->reset(); - // make sure $schema is an object - if (is_array($schema)) { - $schema = self::arrayToObjectRecursive($schema); - } - // set checkMode $initialCheckMode = $this->factory->getConfig(); if ($checkMode !== null) { @@ -60,7 +55,10 @@ public function validate(&$value, $schema = null, $checkMode = null) $this->factory->getSchemaStorage()->addSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI, $schema); $validator = $this->factory->createInstanceFor('schema'); - $validator->check($value, $schema); + $validator->check( + $value, + $this->factory->getSchemaStorage()->getSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI) + ); $this->factory->setConfig($initialCheckMode);