Skip to content

Commit

Permalink
Revert "BREAKING/BUGFIX: Strict coercion of scalar types (webonyx#278)"
Browse files Browse the repository at this point in the history
This reverts commit 975c9fe
  • Loading branch information
mdio committed Sep 30, 2022
1 parent e411398 commit 3ff2ce0
Show file tree
Hide file tree
Showing 11 changed files with 928 additions and 785 deletions.
48 changes: 36 additions & 12 deletions src/Type/Definition/BooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace GraphQL\Type\Definition;

use Exception;
use GraphQL\Error\Error;
use GraphQL\Language\AST\BooleanValueNode;
use GraphQL\Language\AST\Node;
use GraphQL\Language\Printer;
use GraphQL\Utils\Utils;

use function is_array;
use function is_bool;

class BooleanType extends ScalarType
Expand All @@ -17,33 +17,57 @@ class BooleanType extends ScalarType
public ?string $description = 'The `Boolean` scalar type represents `true` or `false`.';

/**
* Serialize the given value to a Boolean.
* Coerce the given value to a boolean.
*
* The GraphQL spec leaves this up to the implementations, so we just do what
* PHP does natively to make this intuitive for developers.
*
* @param mixed $value
*
* @throws Error
*/
public function serialize($value): bool
public function serialize($value) : bool
{
if (is_array($value)) {
throw new Error(
'Boolean cannot represent an array value: ' . Utils::printSafe($value)
);
}

return (bool) $value;
}

public function parseValue($value): bool
/**
* @param mixed $value
*
* @return bool
*
* @throws Error
*/
public function parseValue($value)
{
if (is_bool($value)) {
return $value;
}

$notBoolean = Utils::printSafe($value);
throw new Error("Boolean cannot represent a non boolean value: {$notBoolean}");
throw new Error('Cannot represent value as boolean: ' . Utils::printSafe($value));
}

public function parseLiteral(Node $valueNode, ?array $variables = null): bool
/**
* @param Node $valueNode
* @param mixed[]|null $variables
*
* @return bool|null
*
* @throws Exception
*/
public function parseLiteral($valueNode, ?array $variables = null)
{
if ($valueNode instanceof BooleanValueNode) {
return $valueNode->value;
if (! $valueNode instanceof BooleanValueNode) {
// Intentionally without message, as all information already in wrapped Exception
throw new Exception();
}

$notBoolean = Printer::doPrint($valueNode);
throw new Error("Boolean cannot represent a non boolean value: {$notBoolean}", $valueNode);
return $valueNode->value;
}
}
79 changes: 53 additions & 26 deletions src/Type/Definition/FloatType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@

namespace GraphQL\Type\Definition;

use Exception;
use GraphQL\Error\Error;
use GraphQL\Error\SerializationError;
use GraphQL\Language\AST\FloatValueNode;
use GraphQL\Language\AST\IntValueNode;
use GraphQL\Language\AST\Node;
use GraphQL\Language\Printer;
use GraphQL\Utils\Utils;

use function is_array;
use function is_bool;
use function is_finite;
use function is_float;
use function is_int;
use function is_nan;
use function is_numeric;
use function sprintf;

class FloatType extends ScalarType
{
Expand All @@ -25,43 +24,71 @@ class FloatType extends ScalarType
values as specified by
[IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ';

public function serialize($value): float
/**
* @param mixed $value
*
* @return float|null
*
* @throws Error
*/
public function serialize($value)
{
$float = is_numeric($value) || is_bool($value)
? (float) $value
: null;
return $this->coerceFloat($value);
}

if ($float === null || ! is_finite($float)) {
throw new SerializationError(
'Float cannot represent non numeric value: '
. Utils::printSafe($value)
private function coerceFloat($value)
{
if (is_array($value)) {
throw new Error(
sprintf('Float cannot represent an array value: %s', Utils::printSafe($value))
);
}

return $float;
}
if ($value === '') {
throw new Error(
'Float cannot represent non numeric value: (empty string)'
);
}

public function parseValue($value): float
{
$float = is_float($value) || is_int($value)
? (float) $value
: null;
$float = is_numeric($value) || is_bool($value) ? (float) $value : null;

if ($float === null || ! is_finite($float)) {
$notFloat = Utils::printSafe($value);
throw new Error("Float cannot represent non numeric value: {$notFloat}");
if ($float === null || ! is_finite($float) || is_nan($float)) {
throw new Error(
'Float cannot represent non numeric value: ' .
Utils::printSafe($value)
);
}

return $float;
}

public function parseLiteral(Node $valueNode, ?array $variables = null)
/**
* @param mixed $value
*
* @return float|null
*
* @throws Error
*/
public function parseValue($value)
{
return $this->coerceFloat($value);
}

/**
* @param Node $valueNode
* @param mixed[]|null $variables
*
* @return float|null
*
* @throws Exception
*/
public function parseLiteral($valueNode, ?array $variables = null)
{
if ($valueNode instanceof FloatValueNode || $valueNode instanceof IntValueNode) {
return (float) $valueNode->value;
}

$notFloat = Printer::doPrint($valueNode);
throw new Error("Float cannot represent non numeric value: {$notFloat}", $valueNode);
// Intentionally without message, as all information already in wrapped Exception
throw new Exception();
}
}
69 changes: 52 additions & 17 deletions src/Type/Definition/IDType.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

namespace GraphQL\Type\Definition;

use Exception;
use GraphQL\Error\Error;
use GraphQL\Error\SerializationError;
use GraphQL\Language\AST\IntValueNode;
use GraphQL\Language\AST\Node;
use GraphQL\Language\AST\StringValueNode;
use GraphQL\Language\Printer;
use GraphQL\Utils\Utils;

use function is_array;
use function is_int;
use function is_object;
use function is_scalar;
use function is_string;
use function method_exists;

Expand All @@ -26,37 +26,72 @@ class IDType extends ScalarType
When expected as an input type, any string (such as `"4"`) or integer
(such as `4`) input value will be accepted as an ID.';

public function serialize($value): string
/**
* @param mixed $value
*
* @return string
*
* @throws Error
*/
public function serialize($value)
{
$canCast = is_string($value)
|| is_int($value)
|| (is_object($value) && method_exists($value, '__toString'));

if (! $canCast) {
$notID = Utils::printSafe($value);
throw new SerializationError("ID cannot represent a non-string and non-integer value: {$notID}");
if ($value === true) {
return 'true';
}
if ($value === false) {
return 'false';
}
if ($value === null) {
return 'null';
}
if (is_array($value)) {
throw new Error(
'ID cannot represent an array value: ' . Utils::printSafe($value)
);
}
if (! is_scalar($value) && (! is_object($value) || ! method_exists($value, '__toString'))) {
throw new Error('ID cannot represent non scalar value: ' . Utils::printSafe($value));
}

return (string) $value;
}

public function parseValue($value): string
/**
* @param mixed $value
*
* @return string
*
* @throws Error
*/
public function parseValue($value)
{
if (is_string($value) || is_int($value)) {
return (string) $value;
}
if (is_array($value)) {
throw new Error(
'ID cannot represent an array value: ' . Utils::printSafe($value)
);
}

$notID = Utils::printSafe($value);
throw new Error("ID cannot represent a non-string and non-integer value: {$notID}");
throw new Error('Cannot represent value as ID: ' . Utils::printSafe($value));
}

public function parseLiteral(Node $valueNode, ?array $variables = null): string
/**
* @param Node $valueNode
* @param mixed[]|null $variables
*
* @return string|null
*
* @throws Exception
*/
public function parseLiteral($valueNode, ?array $variables = null)
{
if ($valueNode instanceof StringValueNode || $valueNode instanceof IntValueNode) {
return $valueNode->value;
}

$notID = Printer::doPrint($valueNode);
throw new Error("ID cannot represent a non-string and non-integer value: {$notID}", $valueNode);
// Intentionally without message, as all information already in wrapped Exception
throw new Exception();
}
}
Loading

0 comments on commit 3ff2ce0

Please sign in to comment.