Scalar type serialize method now throws InvariantViolation and parseValue throws UserError

This commit is contained in:
Vladimir Razuvaev 2017-07-18 20:52:39 +07:00
parent 8e3d1eb29b
commit fbcd20814a
4 changed files with 63 additions and 30 deletions

View File

@ -1,6 +1,7 @@
<?php
namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Error\UserError;
use GraphQL\Language\AST\FloatValueNode;
use GraphQL\Language\AST\IntValueNode;
@ -31,7 +32,7 @@ values as specified by
*/
public function serialize($value)
{
return $this->coerceFloat($value);
return $this->coerceFloat($value, false);
}
/**
@ -40,24 +41,29 @@ values as specified by
*/
public function parseValue($value)
{
return $this->coerceFloat($value);
return $this->coerceFloat($value, true);
}
/**
* @param $value
* @param mixed $value
* @param bool $isInput
* @return float|null
*/
private function coerceFloat($value)
private function coerceFloat($value, $isInput)
{
if (is_numeric($value) || $value === true || $value === false) {
return (float) $value;
}
if ($value === '') {
throw new UserError(
'Float cannot represent non numeric value: (empty string)'
$err = 'Float cannot represent non numeric value: (empty string)';
} else {
$err = sprintf(
'Float cannot represent non numeric value: %s',
$isInput ? Utils::printSafeJson($value) : Utils::printSafe($value)
);
}
if (is_numeric($value) || $value === true || $value === false) {
return (float)$value;
}
throw new UserError(sprintf('Float cannot represent non numeric value: %s', Utils::printSafe($value)));
throw ($isInput ? new UserError($err) : new InvariantViolation($err));
}
/**

View File

@ -1,10 +1,11 @@
<?php
namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Error\UserError;
use GraphQL\Language\AST\IntValueNode;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Utils;
use GraphQL\Utils\Utils;
/**
* Class IDType
@ -33,7 +34,19 @@ When expected as an input type, any string (such as `"4"`) or integer
*/
public function serialize($value)
{
return $this->parseValue($value);
if ($value === true) {
return 'true';
}
if ($value === false) {
return 'false';
}
if ($value === null) {
return 'null';
}
if (!is_scalar($value)) {
throw new InvariantViolation("ID type cannot represent non scalar value: " . Utils::printSafe($value));
}
return (string) $value;
}
/**
@ -52,7 +65,7 @@ When expected as an input type, any string (such as `"4"`) or integer
return 'null';
}
if (!is_scalar($value)) {
throw new UserError("String cannot represent non scalar value: " . Utils::printSafe($value));
throw new UserError("ID type cannot represent non scalar value: " . Utils::printSafeJson($value));
}
return (string) $value;
}

View File

@ -38,7 +38,7 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
*/
public function serialize($value)
{
return $this->coerceInt($value);
return $this->coerceInt($value, false);
}
/**
@ -47,21 +47,20 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
*/
public function parseValue($value)
{
try {
return $this->coerceInt($value);
} catch (InvariantViolation $e) {
throw new UserError($e->getMessage(), $e->getCode(), $e);
}
return $this->coerceInt($value, true);
}
/**
* @param $value
* @param bool $isInput
* @return int|null
*/
private function coerceInt($value)
private function coerceInt($value, $isInput)
{
$errClass = $isInput ? UserError::class : InvariantViolation::class;
if ($value === '') {
throw new InvariantViolation(
throw new $errClass(
'Int cannot represent non 32-bit signed integer value: (empty string)'
);
}
@ -69,22 +68,24 @@ values. Int can represent values between -(2^31) and 2^31 - 1. ';
return (int) $value;
}
if (!is_numeric($value) || $value > self::MAX_INT || $value < self::MIN_INT) {
throw new InvariantViolation(
sprintf('Int cannot represent non 32-bit signed integer value: %s', Utils::printSafe($value))
);
throw new $errClass(sprintf(
'Int cannot represent non 32-bit signed integer value: %s',
$isInput ? Utils::printSafeJson($value) : Utils::printSafe($value)
));
}
$num = (float) $value;
// The GraphQL specification does not allow serializing non-integer values
// as Int to avoid accidental data loss.
// Examples: 1.0 == 1; 1.1 != 1, etc
if ($num != (int)$value) {
if ($num != (int) $value) {
// Additionally account for scientific notation (i.e. 1e3), because (float)'1e3' is 1000, but (int)'1e3' is 1
$trimmed = floor($num);
if ($trimmed !== $num) {
throw new InvariantViolation(
'Int cannot represent non-integer value: ' . Utils::printSafe($value)
);
throw new $errClass(sprintf(
'Int cannot represent non-integer value: %s',
$isInput ? Utils::printSafeJson($value) : Utils::printSafe($value)
));
}
}
return (int) $value;

View File

@ -1,9 +1,10 @@
<?php
namespace GraphQL\Type\Definition;
use GraphQL\Error\InvariantViolation;
use GraphQL\Error\UserError;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Utils;
use GraphQL\Utils\Utils;
/**
* Class StringType
@ -30,7 +31,19 @@ represent free-form human-readable text.';
*/
public function serialize($value)
{
return $this->parseValue($value);
if ($value === true) {
return 'true';
}
if ($value === false) {
return 'false';
}
if ($value === null) {
return 'null';
}
if (!is_scalar($value)) {
throw new InvariantViolation("String cannot represent non scalar value: " . Utils::printSafe($value));
}
return (string) $value;
}
/**