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[] */ private $locations; /** * An array describing the JSON-path into the execution response which * corresponds to this error. Only included for errors during execution. * * @var array */ public $path; /** * An array of GraphQL AST Nodes corresponding to this error. * * @var array */ public $nodes; /** * The source GraphQL document corresponding to this error. * * @var Source|null */ private $source; /** * @var array */ private $positions; /** * 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. * * @param $error * @param array|null $nodes * @param array|null $path * @return Error */ public static function createLocatedError($error, $nodes = null, $path = null) { if ($error instanceof self) { return $error; } if ($error instanceof \Exception) { $message = $error->getMessage(); $previous = $error; } else { $message = (string) $error; $previous = null; } return new Error($message, $nodes, null, null, $path, $previous); } /** * @param Error $error * @return array */ public static function formatError(Error $error) { return FormattedError::create($error->getMessage(), $error->getLocations()); } /** * @param string $message * @param array|null $nodes * @param Source $source * @param array|null $positions * @param array|null $path * @param \Exception $previous */ public function __construct($message, $nodes = null, Source $source = null, $positions = null, $path = null, \Exception $previous = null) { parent::__construct($message, 0, $previous); if ($nodes instanceof \Traversable) { $nodes = iterator_to_array($nodes); } $this->nodes = $nodes; $this->source = $source; $this->positions = $positions; $this->path = $path; } /** * @return Source|null */ public function getSource() { if (null === $this->source) { if (!empty($this->nodes[0]) && !empty($this->nodes[0]->loc)) { $this->source = $this->nodes[0]->loc->source; } } 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;}); } } return $this->positions; } /** * @return SourceLocation[] */ 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; } /** * 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->toArray();}); 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 json_encode, * which is a value of any type other than a resource. * @since 5.4.0 */ function jsonSerialize() { return $this->toSerializableArray(); } }