Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ $request = (object)[
'refundAmount'=>"17"
];

$validator = new \JsonSchema\Validator(\JsonSchema\Constraints\Constraint::CHECK_MODE_TYPE_CAST | \JsonSchema\Constraints\Constraint::CHECK_MODE_COERCE);
$validator = new \JsonSchema\Validator(
\JsonSchema\Constraints\Constraint::CHECK_MODE_TYPE_CAST |
\JsonSchema\Constraints\Constraint::CHECK_MODE_COERCE);
$validator->check($request, (object) [
"type"=>"object",
"properties"=>[
Expand Down Expand Up @@ -108,13 +110,15 @@ $jsonSchemaObject = json_decode($jsonSchema);
// The SchemaStorage can resolve references, loading additional schemas from file as needed, etc.
$schemaStorage = new SchemaStorage();

$factory = new \JsonSchema\Constraints\Factory($schemaStorage);

// This does two things:
// 1) Mutates $jsonSchemaObject to normalize the references (to file://mySchema#/definitions/integerData, etc)
// 2) Tells $schemaStorage that references to file://mySchema... should be resolved by looking in $jsonSchemaObject
$schemaStorage->addSchema('file://mySchema', $jsonSchemaObject);

// Provide $schemaStorage to the Validator so that references can be resolved during validation
$jsonValidator = new Validator(Validator::CHECK_MODE_NORMAL, $schemaStorage);
$jsonValidator = new Validator(\JsonSchema\Constraints\Constraint::CHECK_MODE_NORMAL, $factory);

// JSON must be decoded before it can be validated
$jsonToValidateObject = json_decode('{"data":123}');
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/CollectionConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ protected function validateItems($value, $schema = null, JsonPointer $path = nul
// Treat when we have more schema definitions than values, not for empty arrays
if (count($value) > 0) {
for ($k = count($value); $k < count($schema->items); $k++) {
$this->checkUndefined($this->factory->createInstanceFor('undefined'), $schema->items[$k], $path, $k);
$this->checkUndefined($this->factory->createInstanceFor($this->checkMode,'undefined'), $schema->items[$k], $path, $k);
}
}
}
Expand Down
26 changes: 16 additions & 10 deletions src/JsonSchema/Constraints/Constraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ abstract class Constraint implements ConstraintInterface
const CHECK_MODE_TYPE_CAST = 0x00000002;
const CHECK_MODE_COERCE = 0x00000004;

/**
* @var int
*/
protected $checkMode;

/**
* @var Factory
*/
Expand All @@ -37,8 +42,9 @@ abstract class Constraint implements ConstraintInterface
/**
* @param Factory $factory
*/
public function __construct(Factory $factory = null)
public function __construct($checkMode = Constraint::CHECK_MODE_NORMAL, Factory $factory = null)
{
$this->checkMode = $checkMode;
$this->factory = $factory ? : new Factory();
}

Expand Down Expand Up @@ -127,7 +133,7 @@ protected function incrementPath(JsonPointer $path = null, $i)
*/
protected function checkArray($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('collection');
$validator = $this->factory->createInstanceFor($this->checkMode,'collection');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -144,7 +150,7 @@ protected function checkArray($value, $schema = null, JsonPointer $path = null,
*/
protected function checkObject($value, $schema = null, JsonPointer $path = null, $i = null, $patternProperties = null)
{
$validator = $this->factory->createInstanceFor('object');
$validator = $this->factory->createInstanceFor($this->checkMode,'object');
$validator->check($value, $schema, $path, $i, $patternProperties);

$this->addErrors($validator->getErrors());
Expand All @@ -160,7 +166,7 @@ protected function checkObject($value, $schema = null, JsonPointer $path = null,
*/
protected function checkType($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('type');
$validator = $this->factory->createInstanceFor($this->checkMode, 'type');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -176,7 +182,7 @@ protected function checkType($value, $schema = null, JsonPointer $path = null, $
*/
protected function checkUndefined($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('undefined');
$validator = $this->factory->createInstanceFor($this->checkMode,'undefined');

$validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i);

Expand All @@ -193,7 +199,7 @@ protected function checkUndefined($value, $schema = null, JsonPointer $path = nu
*/
protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('string');
$validator = $this->factory->createInstanceFor($this->checkMode, 'string');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -209,7 +215,7 @@ protected function checkString($value, $schema = null, JsonPointer $path = null,
*/
protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('number');
$validator = $this->factory->createInstanceFor($this->checkMode, 'number');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -225,7 +231,7 @@ protected function checkNumber($value, $schema = null, JsonPointer $path = null,
*/
protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('enum');
$validator = $this->factory->createInstanceFor($this->checkMode, 'enum');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -241,7 +247,7 @@ protected function checkEnum($value, $schema = null, JsonPointer $path = null, $
*/
protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('format');
$validator = $this->factory->createInstanceFor($this->checkMode, 'format');
$validator->check($value, $schema, $path, $i);

$this->addErrors($validator->getErrors());
Expand All @@ -254,7 +260,7 @@ protected function checkFormat($value, $schema = null, JsonPointer $path = null,
*/
protected function getTypeCheck()
{
return $this->factory->getTypeCheck();
return $this->factory->getTypeCheck($this->checkMode);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/EnumConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function check($element, $schema = null, JsonPointer $path = null, $i = n

foreach ($schema->enum as $enum) {
$enumType = gettype($enum);
if (($this->factory->getCheckMode() & self::CHECK_MODE_TYPE_CAST) && $type == "array" && $enumType == "object") {
if (($this->checkMode & self::CHECK_MODE_TYPE_CAST) && $type == "array" && $enumType == "object") {
if ((object)$element == $enum) {
return;
}
Expand Down
29 changes: 7 additions & 22 deletions src/JsonSchema/Constraints/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ class Factory
*/
protected $uriRetriever;

/**
* @var int
*/
private $checkMode;

/**
* @var TypeCheck\TypeCheckInterface[]
*/
Expand Down Expand Up @@ -69,12 +64,10 @@ class Factory
*/
public function __construct(
SchemaStorage $schemaStorage = null,
UriRetrieverInterface $uriRetriever = null,
$checkMode = Constraint::CHECK_MODE_NORMAL
UriRetrieverInterface $uriRetriever = null
) {
$this->uriRetriever = $uriRetriever ?: new UriRetriever;
$this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
$this->checkMode = $checkMode;
}

/**
Expand All @@ -90,15 +83,15 @@ public function getSchemaStorage()
return $this->schemaStorage;
}

public function getTypeCheck()
public function getTypeCheck($checkMode)
{
if (!isset($this->typeCheck[$this->checkMode])) {
$this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
if (!isset($this->typeCheck[$checkMode])) {
$this->typeCheck[$checkMode] = ($checkMode & Constraint::CHECK_MODE_TYPE_CAST)
? new TypeCheck\LooseTypeCheck
: new TypeCheck\StrictTypeCheck;
}

return $this->typeCheck[$this->checkMode];
return $this->typeCheck[$checkMode];
}

/**
Expand Down Expand Up @@ -127,24 +120,16 @@ public function setConstraintClass($name, $class)
* @return ConstraintInterface|ObjectConstraint
* @throws InvalidArgumentException if is not possible create the constraint instance.
*/
public function createInstanceFor($constraintName)
public function createInstanceFor($checkMode, $constraintName)
{
if (!isset($this->constraintMap[$constraintName])) {
throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
}

if (!isset($this->instanceCache[$constraintName])) {
$this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
$this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($checkMode, $this);
}

return clone $this->instanceCache[$constraintName];
}

/**
* @return int
*/
public function getCheckMode()
{
return $this->checkMode;
}
}
8 changes: 4 additions & 4 deletions src/JsonSchema/Constraints/ObjectConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public function validateElement($element, $matches, $objectDefinition = null, Js
$this->addError($path, "The presence of the property " . $i . " requires that " . $require . " also be present", 'requires');
}

$property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
$property = $this->getProperty($element, $i, $this->factory->createInstanceFor($this->checkMode, 'undefined'));
if (is_object($property)) {
$this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
}
Expand All @@ -122,17 +122,17 @@ public function validateElement($element, $matches, $objectDefinition = null, Js
*/
public function validateDefinition($element, $objectDefinition = null, JsonPointer $path = null)
{
$undefinedConstraint = $this->factory->createInstanceFor('undefined');
$undefinedConstraint = $this->factory->createInstanceFor($this->checkMode,'undefined');

foreach ($objectDefinition as $i => $value) {
$property = $this->getProperty($element, $i, $undefinedConstraint);
$definition = $this->getProperty($objectDefinition, $i);

if($this->factory->getCheckMode() & Constraint::CHECK_MODE_TYPE_CAST){
if($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST){
if(!($property instanceof Constraint)) {
$property = $this->coerce($property, $definition);

if($this->factory->getCheckMode() & Constraint::CHECK_MODE_COERCE) {
if($this->checkMode & Constraint::CHECK_MODE_COERCE) {
if (is_object($element)) {
$element->{$i} = $property;
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Constraints/TypeConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected function validateTypesArray($value, array $type, &$validTypesWording,
// with a new type constraint
if (is_object($tp)) {
if (!$isValid) {
$validator = $this->factory->createInstanceFor('type');
$validator = $this->factory->createInstanceFor($this->checkMode,'type');
$subSchema = new \stdClass();
$subSchema->type = $tp;
$validator->check($value, $subSchema, $path, null);
Expand Down
2 changes: 1 addition & 1 deletion src/JsonSchema/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Validator extends Constraint
*/
public function check($value, $schema = null, JsonPointer $path = null, $i = null)
{
$validator = $this->factory->createInstanceFor('schema');
$validator = $this->factory->createInstanceFor($this->checkMode, 'schema');
$validator->check($value, $schema);

$this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
Expand Down
8 changes: 4 additions & 4 deletions tests/Constraints/BaseTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function testInvalidCases($input, $schema, $checkMode = Constraint::CHECK
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$validator->check(json_decode($input), $schema);

if (array() !== $errors) {
Expand All @@ -59,7 +59,7 @@ public function testInvalidCasesUsingAssoc($input, $schema, $checkMode = Constra
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$validator->check(json_decode($input, true), $schema);

if (array() !== $errors) {
Expand All @@ -76,7 +76,7 @@ public function testValidCases($input, $schema, $checkMode = Constraint::CHECK_M
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$validator->check(json_decode($input), $schema);

$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
Expand All @@ -96,7 +96,7 @@ public function testValidCasesUsingAssoc($input, $schema, $checkMode = Constrain
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$value = json_decode($input, true);
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));

$validator->check($value, $schema);
$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
Expand Down
8 changes: 4 additions & 4 deletions tests/Constraints/CoerciveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function testValidCoerceCasesUsingAssoc($input, $schema)
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));

$value = json_decode($input, true);

Expand All @@ -45,7 +45,7 @@ public function testValidCoerceCases($input, $schema, $errors = array())
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$value = json_decode($input);

$this->assertTrue(gettype($value->number) == "string");
Expand All @@ -71,7 +71,7 @@ public function testInvalidCoerceCases($input, $schema, $errors = array())
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$validator->check(json_decode($input), $schema);

if (array() !== $errors) {
Expand All @@ -90,7 +90,7 @@ public function testInvalidCoerceCasesUsingAssoc($input, $schema, $errors = arra
$schemaStorage = new SchemaStorage($this->getUriRetrieverMock(json_decode($schema)));
$schema = $schemaStorage->getSchema('http://www.my-domain.com/schema.json');

$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$validator = new Validator($checkMode, new Factory($schemaStorage, null));
$validator->check(json_decode($input, true), $schema);

if (array() !== $errors) {
Expand Down
6 changes: 3 additions & 3 deletions tests/Constraints/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected function setUp()
*/
public function testCreateInstanceForConstraintName($constraintName, $expectedClass)
{
$constraint = $this->factory->createInstanceFor($constraintName);
$constraint = $this->factory->createInstanceFor(Constraint::CHECK_MODE_NORMAL, $constraintName);

$this->assertInstanceOf($expectedClass, $constraint);
$this->assertInstanceOf('JsonSchema\Constraints\ConstraintInterface', $constraint);
Expand Down Expand Up @@ -82,7 +82,7 @@ public function constraintNameProvider()
public function testExceptionWhenCreateInstanceForInvalidConstraintName($constraintName)
{
$this->setExpectedException('JsonSchema\Exception\InvalidArgumentException');
$this->factory->createInstanceFor($constraintName);
$this->factory->createInstanceFor(Constraint::CHECK_MODE_NORMAL, $constraintName);
}

public function invalidConstraintNameProvider() {
Expand Down Expand Up @@ -110,7 +110,7 @@ public function testSetConstraintClassImplementsCondition()
public function testSetConstraintClassInstance()
{
$this->factory->setConstraintClass('string', 'JsonSchema\Tests\Constraints\MyStringConstraint');
$constraint = $this->factory->createInstanceFor('string');
$constraint = $this->factory->createInstanceFor(Constraint::CHECK_MODE_NORMAL, 'string');
$this->assertInstanceOf('JsonSchema\Tests\Constraints\MyStringConstraint', $constraint);
$this->assertInstanceOf('JsonSchema\Constraints\ConstraintInterface', $constraint);
}
Expand Down