From 927997a70556c7452f7ee7bf9fa6be2b3b06fabd Mon Sep 17 00:00:00 2001 From: vladar Date: Fri, 21 Oct 2016 17:42:27 +0700 Subject: [PATCH] Various tools for better error reporting / formatting --- src/Error/FormattedError.php | 105 +++++++++++++++++++++++++++++++ src/Error/InvariantViolation.php | 15 +++++ src/Type/Definition/Config.php | 5 +- src/Utils.php | 3 +- 4 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/Error/InvariantViolation.php diff --git a/src/Error/FormattedError.php b/src/Error/FormattedError.php index 7e35fa3..0106f25 100644 --- a/src/Error/FormattedError.php +++ b/src/Error/FormattedError.php @@ -2,7 +2,15 @@ namespace GraphQL\Error; use GraphQL\Language\SourceLocation; +use GraphQL\Type\Definition\Type; +use GraphQL\Type\Definition\WrappingType; +use GraphQL\Utils; +/** + * Class FormattedError + * @todo move this class to Utils/ErrorUtils + * @package GraphQL\Error + */ class FormattedError { /** @@ -23,4 +31,101 @@ class FormattedError return $formatted; } + + /** + * @param \ErrorException $e + * @return array + */ + public static function createFromPHPError(\ErrorException $e) + { + return [ + 'message' => $e->getMessage(), + 'severity' => $e->getSeverity(), + 'trace' => self::toSafeTrace($e->getTrace()) + ]; + } + + /** + * @param \Exception $e + * @return array + */ + public static function createFromException(\Exception $e) + { + return [ + 'message' => $e->getMessage(), + 'trace' => self::toSafeTrace($e->getTrace()) + ]; + } + + /** + * Converts error trace to serializable array + * + * @param array $trace + * @return array + */ + private static function toSafeTrace(array $trace) + { + // Remove invariant entries as they don't provide much value: + if ( + isset($trace[0]['function']) && isset($trace[0]['class']) && + ('GraphQL\Utils::invariant' === $trace[0]['class'].'::'.$trace[0]['function'])) { + array_shift($trace); + } + + return array_map(function($err) { + $safeErr = array_intersect_key($err, ['file' => true, 'line' => true]); + + if (isset($err['function'])) { + $func = $err['function']; + $args = !empty($err['args']) ? array_map([__CLASS__, 'printVar'], $err['args']) : []; + $funcStr = $func . '(' . implode(", ", $args) . ')'; + + if (isset($err['class'])) { + $safeErr['call'] = $err['class'] . '::' . $funcStr; + } else { + $safeErr['function'] = $funcStr; + } + } + + return $safeErr; + }, $trace); + } + + /** + * @param $var + * @return string + */ + public static function printVar($var) + { + if ($var instanceof Type) { + // FIXME: Replace with schema printer call + if ($var instanceof WrappingType) { + $var = $var->getWrappedType(true); + } + return 'GraphQLType: ' . $var->name; + } + + if (is_object($var)) { + return 'instance of ' . get_class($var) . ($var instanceof \Countable ? '(' . count($var) . ')' : ''); + } + if (is_array($var)) { + return 'array(' . count($var) . ')'; + } + if ('' === $var) { + return '(empty string)'; + } + if (is_string($var)) { + return "'" . addcslashes($var, "'") . "'"; + } + if (is_bool($var)) { + return $var ? 'true' : 'false'; + } + if (is_scalar($var)) { + return $var; + } + if (null === $var) { + return 'null'; + } + return gettype($var); + } } diff --git a/src/Error/InvariantViolation.php b/src/Error/InvariantViolation.php new file mode 100644 index 0000000..f52793f --- /dev/null +++ b/src/Error/InvariantViolation.php @@ -0,0 +1,15 @@ +