Skip to content

Commit

Permalink
Add remaining coercion cases from ajv matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
erayd committed Mar 13, 2017
1 parent 79b5881 commit c9e1276
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 27 deletions.
82 changes: 74 additions & 8 deletions src/JsonSchema/Constraints/TypeConstraint.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ public function check(&$value = null, $schema = null, JsonPointer $path = null,
$wording[] = self::$wording[$type];
}
$this->addError(ConstraintError::TYPE(), $path, array(
'expected' => gettype($value),
'found' => $this->implodeWith($wording, ', ', 'or')
'found' => gettype($value),
'expected' => $this->implodeWith($wording, ', ', 'or')
));
}
}
Expand Down Expand Up @@ -185,6 +185,10 @@ protected function validateType(&$value, $type, $coerce = false)
}

if ('array' === $type) {
if ($coerce) {
$value = $this->toArray($value);
}

return $this->getTypeCheck()->isArray($value);
}

Expand Down Expand Up @@ -213,6 +217,10 @@ protected function validateType(&$value, $type, $coerce = false)
}

if ('string' === $type) {
if ($coerce) {
$value = $this->toString($value);
}

return is_string($value);
}

Expand All @@ -236,19 +244,21 @@ protected function validateType(&$value, $type, $coerce = false)
*/
protected function toBoolean($value)
{
if ($value === 'true') {
if ($value === 1 || $value === 'true') {
return true;
}

if ($value === 'false') {
if (is_null($value) || $value === 0 || $value === 'false') {
return false;
}
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
return $this->toBoolean(reset($value));
}

return $value;
}

/**
* Converts a numeric string to a number. For example, "4" becomes 4.
* Converts a numeric string to a number. For example, "4.5" becomes 4.5.
*
* @param mixed $value the value to convert to a number
*
Expand All @@ -259,16 +269,72 @@ protected function toNumber($value)
if (is_numeric($value)) {
return $value + 0; // cast to number
}
if (is_bool($value) || is_null($value)) {
return (int) $value;
}
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
return $this->toNumber(reset($value));
}

return $value;
}

/**
* Converts a value to an integer. For example, "4" becomes 4.
*
* @param mixed $value
*
* @return int|mixed
*/
protected function toInteger($value)
{
if (is_numeric($value) && (int) $value == $value) {
return (int) $value; // cast to number
$numberValue = $this->toNumber($value);
if (is_numeric($numberValue) && (int) $numberValue == $numberValue) {
return (int) $numberValue; // cast to number
}

return $value;
}

/**
* Converts a value to an array containing that value. For example, [4] becomes 4.
*
* @param mixed $value
*
* @return array|mixed
*/
protected function toArray($value)
{
if (is_scalar($value) || is_null($value)) {
return array($value);
}

return $value;
}

/**
* Convert a value to a string representation of that value. For example, null becomes "".
*
* @param mixed $value
*
* @return string|mixed
*/
protected function toString($value)
{
if (is_numeric($value)) {
return "$value";
}
if ($value === true) {
return 'true';
}
if ($value === false) {
return 'false';
}
if (is_null($value)) {
return '';
}
if ($this->getTypeCheck()->isArray($value) && count($value) === 1) {
return $this->toString(reset($value));
}
}
}
118 changes: 103 additions & 15 deletions tests/Constraints/CoerciveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,75 @@ public function testValidCoerceCases($input, $schema, $errors = array())
$validator = new Validator(new Factory($schemaStorage, null, $checkMode));
$value = json_decode($input);

$this->assertTrue(gettype($value->string) == 'string');
$this->assertTrue(gettype($value->numberString) == 'integer');
$this->assertTrue(gettype($value->boolString) == 'boolean');
$this->assertTrue(gettype($value->boolFalseString) == 'boolean');
$this->assertTrue(gettype($value->nullString) == 'NULL');
$this->assertTrue(gettype($value->arrayString) == 'array');
$this->assertTrue(gettype($value->number) == 'string');
$this->assertTrue(gettype($value->boolNumber) == 'boolean');
$this->assertTrue(gettype($value->nullNumber) == 'NULL');
$this->assertTrue(gettype($value->arrayNumber) == 'array');
$this->assertTrue(gettype($value->integer) == 'string');
$this->assertTrue(gettype($value->negativeInteger) == 'string');
$this->assertTrue(gettype($value->boolean) == 'string');
$this->assertTrue(gettype($value->numberBoolean) == 'integer');
$this->assertTrue(gettype($value->nullBoolean) == 'NULL');
$this->assertTrue(gettype($value->arrayBoolean) == 'array');
$this->assertTrue(gettype($value->array) == 'string');
$this->assertTrue(gettype($value->numberArray) == 'integer');
$this->assertTrue(gettype($value->boolArray) == 'boolean');
$this->assertTrue(gettype($value->nullArray) == 'NULL');

$validator->validate($value, $schema, $checkMode);

$this->assertTrue(gettype($value->string) == 'string');
$this->assertTrue(gettype($value->numberString) == 'string');
$this->assertTrue(gettype($value->boolString) == 'string');
$this->assertTrue(gettype($value->boolFalseString) == 'string');
$this->assertTrue(gettype($value->nullString) == 'string');
$this->assertTrue(gettype($value->arrayString) == 'string');
$this->assertTrue(gettype($value->number) == 'double');
$this->assertTrue(gettype($value->boolNumber) == 'integer');
$this->assertTrue(gettype($value->nullNumber) == 'integer');
$this->assertTrue(gettype($value->arrayNumber) == 'double');
$this->assertTrue(gettype($value->integer) == 'integer');
$this->assertTrue(gettype($value->negativeInteger) == 'integer');
$this->assertTrue(gettype($value->boolean) == 'boolean');

$this->assertTrue($value->number === 1.5);
$this->assertTrue($value->integer === 1);
$this->assertTrue($value->negativeInteger === -2);
$this->assertTrue($value->boolean === true);
$this->assertTrue(gettype($value->numberBoolean) == 'boolean');
$this->assertTrue(gettype($value->nullBoolean) == 'boolean');
$this->assertTrue(gettype($value->arrayBoolean) == 'boolean');
$this->assertTrue(gettype($value->array) == 'array');
$this->assertTrue(gettype($value->numberArray) == 'array');
$this->assertTrue(gettype($value->boolArray) == 'array');
$this->assertTrue(gettype($value->nullArray) == 'array');

$this->assertTrue(gettype($value->multitype1) == 'boolean');
$this->assertTrue(gettype($value->multitype2) == 'double');
$this->assertTrue(gettype($value->multitype3) == 'integer');
$this->assertTrue(gettype($value->multitype4) == 'string');

$this->assertTrue($value->string === 'string test');
$this->assertTrue($value->numberString === '45');
$this->assertTrue($value->boolString === 'true');
$this->assertTrue($value->boolFalseString === 'false');
$this->assertTrue($value->nullString === '');
$this->assertTrue($value->arrayString === '45');
$this->assertTrue($value->number === 1.5);
$this->assertTrue($value->boolNumber === 1);
$this->assertTrue($value->nullNumber === 0);
$this->assertTrue($value->arrayNumber === 1.5);
$this->assertTrue($value->integer === 1);
$this->assertTrue($value->negativeInteger === -2);
$this->assertTrue($value->boolean === true);
$this->assertTrue($value->numberBoolean === true);
$this->assertTrue($value->nullBoolean === false);
$this->assertTrue($value->arrayBoolean === true);
$this->assertTrue($value->array === array('string'));
$this->assertTrue($value->numberArray === array(45));
$this->assertTrue($value->boolArray === array(true));
$this->assertTrue($value->nullArray === array(null));

$this->assertTrue($validator->isValid(), print_r($validator->getErrors(), true));
}
Expand Down Expand Up @@ -123,12 +167,26 @@ public function getValidCoerceTests()
array(
'{
"string":"string test",
"numberString":45,
"boolString":true,
"boolFalseString":false,
"nullString":null,
"arrayString":[45],
"number":"1.5",
"boolNumber":true,
"nullNumber":null,
"arrayNumber":["1.5"],
"integer":"1",
"negativeInteger":"-2",
"boolean":"true",
"numberBoolean":1,
"nullBoolean":null,
"arrayBoolean":["true"],
"object":{},
"array":[],
"array":"string",
"numberArray":45,
"boolArray":true,
"nullArray":null,
"null":null,
"any": "string",
"allOf": "1",
Expand All @@ -149,12 +207,26 @@ public function getValidCoerceTests()
"type":"object",
"properties":{
"string":{"type":"string"},
"numberString":{"type":"string"},
"boolString":{"type":"string"},
"boolFalseString":{"type":"string"},
"nullString":{"type":"string"},
"arrayString":{"type":"string"},
"number":{"type":"number"},
"boolNumber":{"type":"number"},
"nullNumber":{"type":"number"},
"arrayNumber":{"type":"number"},
"integer":{"type":"integer"},
"negativeInteger":{"type":"integer"},
"boolean":{"type":"boolean"},
"numberBoolean":{"type":"boolean"},
"nullBoolean":{"type":"boolean"},
"arrayBoolean":{"type":"boolean"},
"object":{"type":"object"},
"array":{"type":"array"},
"numberArray":{"type":"array"},
"boolArray":{"type":"array"},
"nullArray":{"type":"array"},
"null":{"type":"null"},
"any": {"type":"any"},
"allOf" : {"allOf":[{
Expand Down Expand Up @@ -195,9 +267,11 @@ public function getValidCoerceTests()
public function getInvalidCoerceTests()
{
return array(
array(
array( // #0
'{
"string":null
"string":{
"I am":"an object!"
}
}',
'{
"type":"object",
Expand All @@ -207,7 +281,7 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #1
'{
"number":"five"
}',
Expand All @@ -219,7 +293,7 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #2
'{
"integer":"5.2"
}',
Expand All @@ -231,7 +305,7 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #3
'{
"boolean":"0"
}',
Expand All @@ -243,7 +317,7 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #4
'{
"object":null
}',
Expand All @@ -255,9 +329,11 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #5
'{
"array":null
"array":{
"string":"string"
}
}',
'{
"type":"object",
Expand All @@ -267,7 +343,7 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array(
array( // #6
'{
"null":1
}',
Expand All @@ -279,6 +355,18 @@ public function getInvalidCoerceTests()
"additionalProperties":false
}',
),
array( // #7
'{
"integer":"5f"
}',
'{
"type":"object",
"properties": {
"integer":{"type":"integer"}
},
"additionalProperties":false
}',
),
);
}
}
8 changes: 4 additions & 4 deletions tests/Constraints/OfPropertiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ public function getInvalidTests()
'constraint' => array(
'name' => 'type',
'params' => array(
'expected' => 'array',
'found' => 'a string'
'expected' => 'a string',
'found' => 'array'
)
)
),
Expand All @@ -90,8 +90,8 @@ public function getInvalidTests()
'constraint' => array(
'name' => 'type',
'params' => array(
'expected' => 'array',
'found' => 'a number'
'expected' => 'a number',
'found' => 'array'
)
)
),
Expand Down

0 comments on commit c9e1276

Please sign in to comment.