graphql-php/src/Error.php

208 lines
5.4 KiB
PHP
Raw Normal View History

2015-07-15 23:05:46 +06:00
<?php
namespace GraphQL;
use GraphQL\Language\Source;
use GraphQL\Language\SourceLocation;
/**
* Class Error
* A GraphQLError describes an Error found during the parse, validate, or
* execute phases of performing a GraphQL operation. In addition to a message
* and stack trace, it also includes information about the locations in a
* GraphQL document and/or execution result that correspond to the Error.
*
* @package GraphQL
*/
class Error extends \Exception implements \JsonSerializable
2015-07-15 23:05:46 +06:00
{
/**
* A message describing the Error for debugging purposes.
*
2015-07-15 23:05:46 +06:00
* @var string
*/
public $message;
/**
* An array of [ line => x, column => y] locations within the source GraphQL document
* which correspond to this error.
*
* Errors during validation often contain multiple locations, for example to
* point out two things with the same name. Errors during execution include a
* single location, the field which produced the error.
*
* @var SourceLocation[]
2015-07-15 23:05:46 +06:00
*/
private $locations;
2015-07-15 23:05:46 +06:00
/**
* An array describing the JSON-path into the execution response which
* corresponds to this error. Only included for errors during execution.
*
2015-07-15 23:05:46 +06:00
* @var array
*/
public $path;
2015-07-15 23:05:46 +06:00
/**
* An array of GraphQL AST Nodes corresponding to this error.
*
* @var array
2015-07-15 23:05:46 +06:00
*/
public $nodes;
2015-07-15 23:05:46 +06:00
/**
* The source GraphQL document corresponding to this error.
*
2015-07-15 23:05:46 +06:00
* @var Source|null
*/
2015-08-16 16:39:30 +06:00
private $source;
2015-07-15 23:05:46 +06:00
/**
* @var array
*/
private $positions;
2015-07-15 23:05:46 +06:00
/**
2015-08-16 16:39:30 +06:00
* Given an arbitrary Error, presumably thrown while attempting to execute a
* GraphQL operation, produce a new GraphQLError aware of the location in the
* document responsible for the original Error.
*
2015-07-15 23:05:46 +06:00
* @param $error
2015-08-16 16:39:30 +06:00
* @param array|null $nodes
* @param array|null $path
2015-08-16 16:39:30 +06:00
* @return Error
2015-07-15 23:05:46 +06:00
*/
public static function createLocatedError($error, $nodes = null, $path = null)
2015-07-15 23:05:46 +06:00
{
if ($error instanceof self) {
return $error;
}
2015-08-16 16:39:30 +06:00
if ($error instanceof \Exception) {
$message = $error->getMessage();
$previous = $error;
2015-07-15 23:05:46 +06:00
} else {
$message = (string) $error;
2015-08-16 16:39:30 +06:00
$previous = null;
2015-07-15 23:05:46 +06:00
}
return new Error($message, $nodes, null, null, $path, $previous);
2015-07-15 23:05:46 +06:00
}
/**
2015-08-16 16:39:30 +06:00
* @param Error $error
* @return array
2015-08-16 16:39:30 +06:00
*/
public static function formatError(Error $error)
{
return $error->toSerializableArray();
2015-08-16 16:39:30 +06:00
}
/**
* @param string $message
2015-07-15 23:05:46 +06:00
* @param array|null $nodes
2015-08-16 16:39:30 +06:00
* @param Source $source
* @param array|null $positions
* @param array|null $path
* @param \Exception $previous
2015-08-16 16:39:30 +06:00
*/
public function __construct($message, $nodes = null, Source $source = null, $positions = null, $path = null, \Exception $previous = null)
2015-08-16 16:39:30 +06:00
{
parent::__construct($message, 0, $previous);
if ($nodes instanceof \Traversable) {
$nodes = iterator_to_array($nodes);
}
2015-08-16 16:39:30 +06:00
$this->nodes = $nodes;
$this->source = $source;
$this->positions = $positions;
$this->path = $path;
2015-08-16 16:39:30 +06:00
}
/**
* @return Source|null
2015-07-15 23:05:46 +06:00
*/
2015-08-16 16:39:30 +06:00
public function getSource()
2015-07-15 23:05:46 +06:00
{
2015-08-16 16:39:30 +06:00
if (null === $this->source) {
if (!empty($this->nodes[0]) && !empty($this->nodes[0]->loc)) {
$this->source = $this->nodes[0]->loc->source;
2015-07-15 23:05:46 +06:00
}
}
2015-08-16 16:39:30 +06:00
return $this->source;
}
/**
* @return array
*/
public function getPositions()
{
if (null === $this->positions) {
if (!empty($this->nodes)) {
$positions = array_map(function($node) { return isset($node->loc) ? $node->loc->start : null; }, $this->nodes);
$this->positions = array_filter($positions, function($p) {return $p !== null;});
2015-08-16 16:39:30 +06:00
}
}
return $this->positions;
}
/**
* @return SourceLocation[]
2015-08-16 16:39:30 +06:00
*/
public function getLocations()
{
if (null === $this->locations) {
$positions = $this->getPositions();
$source = $this->getSource();
if ($positions && $source) {
$this->locations = array_map(function ($pos) use ($source) {
return $source->getLocation($pos);
}, $positions);
} else {
$this->locations = [];
}
}
return $this->locations;
2015-07-15 23:05:46 +06:00
}
/**
* Returns array representation of error suitable for serialization
*
* @return array
*/
public function toSerializableArray()
{
$arr = [
'message' => $this->getMessage(),
];
$locations = Utils::map($this->getLocations(), function(SourceLocation $loc) {
return $loc->toSerializableArray();
});
if (!empty($locations)) {
$arr['locations'] = $locations;
}
if (!empty($this->path)) {
$arr['path'] = $this->path;
}
return $arr;
}
/**
* Specify data which should be serialized to JSON
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
function jsonSerialize()
{
return $this->toSerializableArray();
}
2015-07-15 23:05:46 +06:00
}