path && $error->nodes) { return $error; } else { $nodes = $nodes ?: $error->nodes; $path = $path ?: $error->path; } } $source = $positions = $originalError = null; if ($error instanceof self) { $message = $error->getMessage(); $originalError = $error; $nodes = $error->nodes ?: $nodes; $source = $error->source; $positions = $error->positions; } else if ($error instanceof \Exception || $error instanceof \Throwable) { $message = $error->getMessage(); $originalError = $error; } else { $message = (string) $error; } return new static( $message ?: 'An unknown error occurred.', $nodes, $source, $positions, $path, $originalError ); } /** * @param Error $error * @return array */ public static function formatError(Error $error) { return $error->toSerializableArray(); } /** * @param string $message * @param array|null $nodes * @param Source $source * @param array|null $positions * @param array|null $path * @param \Throwable $previous */ public function __construct( $message, $nodes = null, Source $source = null, $positions = null, $path = null, $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; if ($previous instanceof ClientAware) { $this->isClientSafe = $previous->isClientSafe(); $this->category = $previous->getCategory() ?: static::CATEGORY_INTERNAL; } else if ($previous) { $this->isClientSafe = false; $this->category = static::CATEGORY_INTERNAL; } else { $this->isClientSafe = true; $this->category = static::CATEGORY_GRAPHQL; } } /** * @inheritdoc */ public function isClientSafe() { return $this->isClientSafe; } /** * @inheritdoc */ public function getCategory() { return $this->category; } /** * @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; } /** * An array of locations within the source GraphQL document which correspond to this error. * * Each entry has information about `line` and `column` within source GraphQL document: * $location->line; * $location->column; * * Errors during validation often contain multiple locations, for example to * point out to field mentioned in multiple fragments. Errors during execution include a * single location, the field which produced the error. * * @api * @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 an array describing the path from the root value to the field which produced this error. * Only included for execution errors. * * @api * @return array|null */ public function getPath() { return $this->path; } /** * Returns array representation of error suitable for serialization * * @deprecated Use FormattedError::createFromException() instead * @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 json_encode, * which is a value of any type other than a resource. * @since 5.4.0 */ function jsonSerialize() { return $this->toSerializableArray(); } }