mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 06:16:05 +03:00
Improved docblock comments (suitable for reference docs generation)
This commit is contained in:
parent
3ef2d2827b
commit
1b4f983f3f
@ -2,24 +2,29 @@
|
|||||||
namespace GraphQL\Error;
|
namespace GraphQL\Error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface ClientAware
|
* This interface is used for [default error formatting](error-handling/).
|
||||||
*
|
*
|
||||||
* @package GraphQL\Error
|
* Only errors implementing this interface (and returning true from `isClientSafe()`)
|
||||||
|
* will be formatted with original error message.
|
||||||
|
*
|
||||||
|
* All other errors will be formatted with generic "Internal server error".
|
||||||
*/
|
*/
|
||||||
interface ClientAware
|
interface ClientAware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns true when exception message is safe to be displayed to client
|
* Returns true when exception message is safe to be displayed to a client.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isClientSafe();
|
public function isClientSafe();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns string describing error category.
|
* Returns string describing a category of the error.
|
||||||
*
|
*
|
||||||
* Value "graphql" is reserved for errors produced by query parsing or validation, do not use it.
|
* Value "graphql" is reserved for errors produced by query parsing or validation, do not use it.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getCategory();
|
public function getCategory();
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Error;
|
namespace GraphQL\Error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of flags for [error debugging](error-handling/#debugging-tools).
|
||||||
|
*/
|
||||||
class Debug
|
class Debug
|
||||||
{
|
{
|
||||||
const INCLUDE_DEBUG_MESSAGE = 1;
|
const INCLUDE_DEBUG_MESSAGE = 1;
|
||||||
|
@ -6,13 +6,18 @@ use GraphQL\Language\SourceLocation;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Error
|
* Describes an Error found during the parse, validate, or
|
||||||
* A GraphQLError describes an Error found during the parse, validate, or
|
|
||||||
* execute phases of performing a GraphQL operation. In addition to a message
|
* execute phases of performing a GraphQL operation. In addition to a message
|
||||||
* and stack trace, it also includes information about the locations in a
|
* and stack trace, it also includes information about the locations in a
|
||||||
* GraphQL document and/or execution result that correspond to the Error.
|
* GraphQL document and/or execution result that correspond to the Error.
|
||||||
*
|
*
|
||||||
* @package GraphQL
|
* When the error was caused by an exception thrown in resolver, original exception
|
||||||
|
* is available via `getPrevious()`.
|
||||||
|
*
|
||||||
|
* Also read related docs on [error handling](error-handling/)
|
||||||
|
*
|
||||||
|
* Class extends standard PHP `\Exception`, so all standard methods of base `\Exception` class
|
||||||
|
* are available in addition to those listed below.
|
||||||
*/
|
*/
|
||||||
class Error extends \Exception implements \JsonSerializable, ClientAware
|
class Error extends \Exception implements \JsonSerializable, ClientAware
|
||||||
{
|
{
|
||||||
@ -27,13 +32,6 @@ class Error extends \Exception implements \JsonSerializable, ClientAware
|
|||||||
public $message;
|
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[]
|
* @var SourceLocation[]
|
||||||
*/
|
*/
|
||||||
private $locations;
|
private $locations;
|
||||||
@ -219,6 +217,17 @@ class Error extends \Exception implements \JsonSerializable, ClientAware
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 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[]
|
* @return SourceLocation[]
|
||||||
*/
|
*/
|
||||||
public function getLocations()
|
public function getLocations()
|
||||||
@ -240,9 +249,10 @@ class Error extends \Exception implements \JsonSerializable, ClientAware
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array describing the JSON-path into the execution response which
|
* Returns an array describing the path from the root value to the field which produced this error.
|
||||||
* corresponds to this error. Only included for errors during execution.
|
* Only included for execution errors.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return array|null
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
public function getPath()
|
public function getPath()
|
||||||
|
@ -7,23 +7,36 @@ use GraphQL\Type\Definition\WrappingType;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class FormattedError
|
* This class is used for [default error formatting](error-handling/).
|
||||||
*
|
* It converts PHP exceptions to [spec-compliant errors](https://facebook.github.io/graphql/#sec-Errors)
|
||||||
* @package GraphQL\Error
|
* and provides tools for error debugging.
|
||||||
*/
|
*/
|
||||||
class FormattedError
|
class FormattedError
|
||||||
{
|
{
|
||||||
private static $internalErrorMessage = 'Internal server error';
|
private static $internalErrorMessage = 'Internal server error';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default error message for internal errors formatted using createFormattedError().
|
||||||
|
* This value can be overridden by passing 3rd argument to `createFormattedError()`.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param string $msg
|
||||||
|
*/
|
||||||
public static function setInternalErrorMessage($msg)
|
public static function setInternalErrorMessage($msg)
|
||||||
{
|
{
|
||||||
self::$internalErrorMessage = $msg;
|
self::$internalErrorMessage = $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard GraphQL error formatter. Converts any exception to GraphQL error
|
* Standard GraphQL error formatter. Converts any exception to array
|
||||||
* conforming to GraphQL spec
|
* conforming to GraphQL spec.
|
||||||
*
|
*
|
||||||
|
* This method only exposes exception message when exception implements ClientAware interface
|
||||||
|
* (or when debug flags are passed).
|
||||||
|
*
|
||||||
|
* For a list of available debug flags see GraphQL\Error\Debug constants.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param \Throwable $e
|
* @param \Throwable $e
|
||||||
* @param bool|int $debug
|
* @param bool|int $debug
|
||||||
* @param string $internalErrorMessage
|
* @param string $internalErrorMessage
|
||||||
@ -73,6 +86,9 @@ class FormattedError
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Decorates spec-compliant $formattedError with debug entries according to $debug flags
|
||||||
|
* (see GraphQL\Error\Debug for available flags)
|
||||||
|
*
|
||||||
* @param array $formattedError
|
* @param array $formattedError
|
||||||
* @param \Throwable $e
|
* @param \Throwable $e
|
||||||
* @param bool $debug
|
* @param bool $debug
|
||||||
@ -148,8 +164,9 @@ class FormattedError
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts error trace to serializable array
|
* Returns error trace as serializable array
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param \Throwable $error
|
* @param \Throwable $error
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Error;
|
namespace GraphQL\Error;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates warnings produced by the library.
|
||||||
|
*
|
||||||
|
* Warnings can be suppressed (individually or all) if required.
|
||||||
|
* Also it is possible to override warning handler (which is **trigger_error()** by default)
|
||||||
|
*/
|
||||||
final class Warning
|
final class Warning
|
||||||
{
|
{
|
||||||
const NAME_WARNING = 1;
|
const WARNING_NAME = 1;
|
||||||
const ASSIGN_WARNING = 2;
|
const WARNING_ASSIGN = 2;
|
||||||
const CONFIG_WARNING = 4;
|
const WARNING_CONFIG = 4;
|
||||||
const FULL_SCHEMA_SCAN_WARNING = 8;
|
const WARNING_FULL_SCHEMA_SCAN = 8;
|
||||||
const CONFIG_DEPRECATION_WARNING = 16;
|
const WARNING_CONFIG_DEPRECATION = 16;
|
||||||
const NOT_A_TYPE = 32;
|
const WARNING_NOT_A_TYPE = 32;
|
||||||
|
|
||||||
const ALL = 63;
|
const ALL = 63;
|
||||||
|
|
||||||
static $enableWarnings = self::ALL;
|
static $enableWarnings = self::ALL;
|
||||||
@ -19,9 +24,10 @@ final class Warning
|
|||||||
static private $warningHandler;
|
static private $warningHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets warning handler which (when set) will intercept all system warnings.
|
* Sets warning handler which can intercept all system warnings.
|
||||||
* When not set, trigger_error() is used to notify about warnings.
|
* When not set, trigger_error() is used to notify about warnings.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param callable|null $warningHandler
|
* @param callable|null $warningHandler
|
||||||
*/
|
*/
|
||||||
public static function setWarningHandler(callable $warningHandler = null)
|
public static function setWarningHandler(callable $warningHandler = null)
|
||||||
@ -33,10 +39,11 @@ final class Warning
|
|||||||
* Suppress warning by id (has no effect when custom warning handler is set)
|
* Suppress warning by id (has no effect when custom warning handler is set)
|
||||||
*
|
*
|
||||||
* Usage example:
|
* Usage example:
|
||||||
* Warning::suppress(Warning::NOT_A_TYPE)
|
* Warning::suppress(Warning::WARNING_NOT_A_TYPE)
|
||||||
*
|
*
|
||||||
* When passing true - suppresses all warnings.
|
* When passing true - suppresses all warnings.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param bool|int $suppress
|
* @param bool|int $suppress
|
||||||
*/
|
*/
|
||||||
static function suppress($suppress = true)
|
static function suppress($suppress = true)
|
||||||
@ -55,10 +62,11 @@ final class Warning
|
|||||||
* Re-enable previously suppressed warning by id
|
* Re-enable previously suppressed warning by id
|
||||||
*
|
*
|
||||||
* Usage example:
|
* Usage example:
|
||||||
* Warning::suppress(Warning::NOT_A_TYPE)
|
* Warning::suppress(Warning::WARNING_NOT_A_TYPE)
|
||||||
*
|
*
|
||||||
* When passing true - re-enables all warnings.
|
* When passing true - re-enables all warnings.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param bool|int $enable
|
* @param bool|int $enable
|
||||||
*/
|
*/
|
||||||
public static function enable($enable = true)
|
public static function enable($enable = true)
|
||||||
|
@ -11,6 +11,8 @@ use GraphQL\Type\Schema;
|
|||||||
*
|
*
|
||||||
* Namely, schema of the type system that is currently executing,
|
* Namely, schema of the type system that is currently executing,
|
||||||
* and the fragments defined in the query document
|
* and the fragments defined in the query document
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
*/
|
*/
|
||||||
class ExecutionContext
|
class ExecutionContext
|
||||||
{
|
{
|
||||||
|
@ -4,19 +4,40 @@ namespace GraphQL\Executor;
|
|||||||
use GraphQL\Error\Error;
|
use GraphQL\Error\Error;
|
||||||
use GraphQL\Error\FormattedError;
|
use GraphQL\Error\FormattedError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returned after [query execution](executing-queries/).
|
||||||
|
* Represents both - result of successful execution and of a failed one
|
||||||
|
* (with errors collected in `errors` prop)
|
||||||
|
*
|
||||||
|
* Could be converted to [spec-compliant](https://facebook.github.io/graphql/#sec-Response-Format)
|
||||||
|
* serializable array using `toArray()`
|
||||||
|
*/
|
||||||
class ExecutionResult implements \JsonSerializable
|
class ExecutionResult implements \JsonSerializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Data collected from resolvers during query execution
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $data;
|
public $data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Error[]
|
* Errors registered during query execution.
|
||||||
|
*
|
||||||
|
* If an error was caused by exception thrown in resolver, $error->getPrevious() would
|
||||||
|
* contain original exception.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @var \GraphQL\Error\Error[]
|
||||||
*/
|
*/
|
||||||
public $errors;
|
public $errors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* User-defined serializable array of extensions included in serialized result.
|
||||||
|
* Conforms to
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $extensions;
|
public $extensions;
|
||||||
@ -56,6 +77,7 @@ class ExecutionResult implements \JsonSerializable
|
|||||||
* // ... other keys
|
* // ... other keys
|
||||||
* );
|
* );
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param callable $errorFormatter
|
* @param callable $errorFormatter
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -75,6 +97,7 @@ class ExecutionResult implements \JsonSerializable
|
|||||||
* return array_map($formatter, $errors);
|
* return array_map($formatter, $errors);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param callable $handler
|
* @param callable $handler
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -85,11 +108,16 @@ class ExecutionResult implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts GraphQL result to array using provided errors handler and formatter.
|
* Converts GraphQL query result to spec-compliant serializable array using provided
|
||||||
|
* errors handler and formatter.
|
||||||
*
|
*
|
||||||
* Default error formatter is GraphQL\Error\FormattedError::createFromException
|
* If debug argument is passed, output of error formatter is enriched which debugging information
|
||||||
* Default error handler will simply return all errors formatted. No errors are filtered.
|
* ("debugMessage", "trace" keys depending on flags).
|
||||||
*
|
*
|
||||||
|
* $debug argument must be either bool (only adds "debugMessage" to result) or sum of flags from
|
||||||
|
* GraphQL\Error\Debug
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param bool|int $debug
|
* @param bool|int $debug
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -31,23 +31,7 @@ use GraphQL\Utils\TypeInfo;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Terminology
|
* Implements the "Evaluating requests" section of the GraphQL specification.
|
||||||
*
|
|
||||||
* "Definitions" are the generic name for top-level statements in the document.
|
|
||||||
* Examples of this include:
|
|
||||||
* 1) Operations (such as a query)
|
|
||||||
* 2) Fragments
|
|
||||||
*
|
|
||||||
* "Operations" are a generic name for requests in the document.
|
|
||||||
* Examples of this include:
|
|
||||||
* 1) query,
|
|
||||||
* 2) mutation
|
|
||||||
*
|
|
||||||
* "Selections" are the statements that can appear legally and at
|
|
||||||
* single level of the query. These include:
|
|
||||||
* 1) field references e.g "a"
|
|
||||||
* 2) fragment "spreads" e.g. "...c"
|
|
||||||
* 3) inline fragment "spreads" e.g. "...on Type { a }"
|
|
||||||
*/
|
*/
|
||||||
class Executor
|
class Executor
|
||||||
{
|
{
|
||||||
@ -88,8 +72,12 @@ class Executor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes DocumentNode against given schema
|
* Executes DocumentNode against given $schema.
|
||||||
*
|
*
|
||||||
|
* Always returns ExecutionResult and never throws. All errors which occur during operation
|
||||||
|
* execution are collected in `$result->errors`.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param Schema $schema
|
* @param Schema $schema
|
||||||
* @param DocumentNode $ast
|
* @param DocumentNode $ast
|
||||||
* @param $rootValue
|
* @param $rootValue
|
||||||
@ -134,9 +122,12 @@ class Executor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes DocumentNode against given $schema using given $promiseAdapter for deferred resolvers.
|
* Same as executeQuery(), but requires promise adapter and returns a promise which is always
|
||||||
* Returns promise which is always fullfilled with instance of ExecutionResult
|
* fulfilled with an instance of ExecutionResult and never rejected.
|
||||||
*
|
*
|
||||||
|
* Useful for async PHP platforms.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param PromiseAdapter $promiseAdapter
|
* @param PromiseAdapter $promiseAdapter
|
||||||
* @param Schema $schema
|
* @param Schema $schema
|
||||||
* @param DocumentNode $ast
|
* @param DocumentNode $ast
|
||||||
@ -1083,7 +1074,7 @@ class Executor
|
|||||||
'for value: ' . Utils::printSafe($result) . '. Switching to slow resolution method using `isTypeOf` ' .
|
'for value: ' . Utils::printSafe($result) . '. Switching to slow resolution method using `isTypeOf` ' .
|
||||||
'of all possible implementations. It requires full schema scan and degrades query performance significantly. '.
|
'of all possible implementations. It requires full schema scan and degrades query performance significantly. '.
|
||||||
' Make sure your `resolveType` always returns valid implementation or throws.',
|
' Make sure your `resolveType` always returns valid implementation or throws.',
|
||||||
Warning::FULL_SCHEMA_SCAN_WARNING
|
Warning::WARNING_FULL_SCHEMA_SCAN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
$runtimeType = self::defaultTypeResolver($result, $exeContext->contextValue, $info, $returnType);
|
||||||
|
@ -1,19 +1,24 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Executor\Promise;
|
namespace GraphQL\Executor\Promise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a means for integration of async PHP platforms ([related docs](data-fetching/#async-php))
|
||||||
|
*/
|
||||||
interface PromiseAdapter
|
interface PromiseAdapter
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Return true if value is promise of underlying system
|
* Return true if the value is a promise or a deferred of the underlying platform
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isThenable($value);
|
public function isThenable($value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts thenable of underlying system into Promise instance
|
* Converts thenable of the underlying platform into GraphQL\Executor\Promise\Promise instance
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param object $thenable
|
* @param object $thenable
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
@ -21,8 +26,9 @@ interface PromiseAdapter
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts our Promise wrapper, extracts adopted promise out of it and executes actual `then` logic described
|
* Accepts our Promise wrapper, extracts adopted promise out of it and executes actual `then` logic described
|
||||||
* in Promises/A+ specs. Then returns new wrapped Promise instance.
|
* in Promises/A+ specs. Then returns new wrapped instance of GraphQL\Executor\Promise\Promise.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Promise $promise
|
* @param Promise $promise
|
||||||
* @param callable|null $onFulfilled
|
* @param callable|null $onFulfilled
|
||||||
* @param callable|null $onRejected
|
* @param callable|null $onRejected
|
||||||
@ -34,8 +40,11 @@ interface PromiseAdapter
|
|||||||
/**
|
/**
|
||||||
* Creates a Promise
|
* Creates a Promise
|
||||||
*
|
*
|
||||||
|
* Expected resolver signature:
|
||||||
|
* function(callable $resolve, callable $reject)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param callable $resolver
|
* @param callable $resolver
|
||||||
|
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
public function create(callable $resolver);
|
public function create(callable $resolver);
|
||||||
@ -43,8 +52,8 @@ interface PromiseAdapter
|
|||||||
/**
|
/**
|
||||||
* Creates a fulfilled Promise for a value if the value is not a promise.
|
* Creates a fulfilled Promise for a value if the value is not a promise.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
public function createFulfilled($value = null);
|
public function createFulfilled($value = null);
|
||||||
@ -53,8 +62,8 @@ interface PromiseAdapter
|
|||||||
* Creates a rejected promise for a reason if the reason is not a promise. If
|
* Creates a rejected promise for a reason if the reason is not a promise. If
|
||||||
* the provided reason is a promise, then it is returned as-is.
|
* the provided reason is a promise, then it is returned as-is.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param \Throwable $reason
|
* @param \Throwable $reason
|
||||||
*
|
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
public function createRejected($reason);
|
public function createRejected($reason);
|
||||||
@ -63,8 +72,8 @@ interface PromiseAdapter
|
|||||||
* Given an array of promises (or values), returns a promise that is fulfilled when all the
|
* Given an array of promises (or values), returns a promise that is fulfilled when all the
|
||||||
* items in the array are fulfilled.
|
* items in the array are fulfilled.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param array $promisesOrValues Promises or values.
|
* @param array $promisesOrValues Promises or values.
|
||||||
*
|
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
public function all(array $promisesOrValues);
|
public function all(array $promisesOrValues);
|
||||||
|
@ -13,26 +13,34 @@ use GraphQL\Executor\Promise\PromiseAdapter;
|
|||||||
use GraphQL\Type\Definition\Directive;
|
use GraphQL\Type\Definition\Directive;
|
||||||
use GraphQL\Type\Definition\Type;
|
use GraphQL\Type\Definition\Type;
|
||||||
use GraphQL\Validator\DocumentValidator;
|
use GraphQL\Validator\DocumentValidator;
|
||||||
|
use GraphQL\Validator\Rules\AbstractValidationRule;
|
||||||
use GraphQL\Validator\Rules\QueryComplexity;
|
use GraphQL\Validator\Rules\QueryComplexity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the primary facade for fulfilling GraphQL operations.
|
||||||
|
* See [related documentation](executing-queries/).
|
||||||
|
*/
|
||||||
class GraphQL
|
class GraphQL
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* This is the primary entry point function for fulfilling GraphQL operations
|
* Executes graphql query.
|
||||||
* by parsing, validating, and executing a GraphQL document along side a
|
|
||||||
* GraphQL schema.
|
|
||||||
*
|
*
|
||||||
* More sophisticated GraphQL servers, such as those which persist queries,
|
* More sophisticated GraphQL servers, such as those which persist queries,
|
||||||
* may wish to separate the validation and execution phases to a static time
|
* may wish to separate the validation and execution phases to a static time
|
||||||
* tooling step, and a server runtime step.
|
* tooling step, and a server runtime step.
|
||||||
*
|
*
|
||||||
|
* Available options:
|
||||||
|
*
|
||||||
* schema:
|
* schema:
|
||||||
* The GraphQL type system to use when validating and executing a query.
|
* The GraphQL type system to use when validating and executing a query.
|
||||||
* requestString:
|
* source:
|
||||||
* A GraphQL language formatted string representing the requested operation.
|
* A GraphQL language formatted string representing the requested operation.
|
||||||
* rootValue:
|
* rootValue:
|
||||||
* The value provided as the first argument to resolver functions on the top
|
* The value provided as the first argument to resolver functions on the top
|
||||||
* level type (e.g. the query object type).
|
* level type (e.g. the query object type).
|
||||||
|
* context:
|
||||||
|
* The value provided as the third argument to all resolvers.
|
||||||
|
* Use this to pass current session, user data, etc
|
||||||
* variableValues:
|
* variableValues:
|
||||||
* A mapping of variable name to runtime value to use for all variables
|
* A mapping of variable name to runtime value to use for all variables
|
||||||
* defined in the requestString.
|
* defined in the requestString.
|
||||||
@ -49,6 +57,7 @@ class GraphQL
|
|||||||
* Empty array would allow to skip query validation (may be convenient for persisted
|
* Empty array would allow to skip query validation (may be convenient for persisted
|
||||||
* queries which are validated before persisting and assumed valid during execution)
|
* queries which are validated before persisting and assumed valid during execution)
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param \GraphQL\Type\Schema $schema
|
* @param \GraphQL\Type\Schema $schema
|
||||||
* @param string|DocumentNode $source
|
* @param string|DocumentNode $source
|
||||||
* @param mixed $rootValue
|
* @param mixed $rootValue
|
||||||
@ -80,8 +89,10 @@ class GraphQL
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as executeQuery(), but requires PromiseAdapter and always returns a Promise
|
* Same as executeQuery(), but requires PromiseAdapter and always returns a Promise.
|
||||||
|
* Useful for Async PHP platforms.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param PromiseAdapter $promiseAdapter
|
* @param PromiseAdapter $promiseAdapter
|
||||||
* @param \GraphQL\Type\Schema $schema
|
* @param \GraphQL\Type\Schema $schema
|
||||||
* @param string|DocumentNode $source
|
* @param string|DocumentNode $source
|
||||||
@ -230,6 +241,7 @@ class GraphQL
|
|||||||
/**
|
/**
|
||||||
* Returns directives defined in GraphQL spec
|
* Returns directives defined in GraphQL spec
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return Directive[]
|
* @return Directive[]
|
||||||
*/
|
*/
|
||||||
public static function getStandardDirectives()
|
public static function getStandardDirectives()
|
||||||
@ -240,6 +252,7 @@ class GraphQL
|
|||||||
/**
|
/**
|
||||||
* Returns types defined in GraphQL spec
|
* Returns types defined in GraphQL spec
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return Type[]
|
* @return Type[]
|
||||||
*/
|
*/
|
||||||
public static function getStandardTypes()
|
public static function getStandardTypes()
|
||||||
@ -248,7 +261,10 @@ class GraphQL
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* Returns standard validation rules implementing GraphQL spec
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return AbstractValidationRule[]
|
||||||
*/
|
*/
|
||||||
public static function getStandardValidationRules()
|
public static function getStandardValidationRules()
|
||||||
{
|
{
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Language;
|
namespace GraphQL\Language;
|
||||||
|
|
||||||
// language/parser.js
|
|
||||||
|
|
||||||
use GraphQL\Language\AST\ArgumentNode;
|
use GraphQL\Language\AST\ArgumentNode;
|
||||||
use GraphQL\Language\AST\DirectiveDefinitionNode;
|
use GraphQL\Language\AST\DirectiveDefinitionNode;
|
||||||
use GraphQL\Language\AST\EnumTypeDefinitionNode;
|
use GraphQL\Language\AST\EnumTypeDefinitionNode;
|
||||||
@ -45,9 +43,15 @@ use GraphQL\Language\AST\VariableNode;
|
|||||||
use GraphQL\Language\AST\VariableDefinitionNode;
|
use GraphQL\Language\AST\VariableDefinitionNode;
|
||||||
use GraphQL\Error\SyntaxError;
|
use GraphQL\Error\SyntaxError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses string containing GraphQL query or [type definition](type-system/type-language/) to Abstract Syntax Tree.
|
||||||
|
*/
|
||||||
class Parser
|
class Parser
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Given a GraphQL source, parses it into a `GraphQL\Language\AST\DocumentNode`.
|
||||||
|
* Throws `GraphQL\Error\SyntaxError` if a syntax error is encountered.
|
||||||
|
*
|
||||||
* Available options:
|
* Available options:
|
||||||
*
|
*
|
||||||
* noLocation: boolean,
|
* noLocation: boolean,
|
||||||
@ -55,6 +59,7 @@ class Parser
|
|||||||
* in the source that they correspond to. This configuration flag
|
* in the source that they correspond to. This configuration flag
|
||||||
* disables that behavior for performance or testing.)
|
* disables that behavior for performance or testing.)
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Source|string $source
|
* @param Source|string $source
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return DocumentNode
|
* @return DocumentNode
|
||||||
@ -66,17 +71,17 @@ class Parser
|
|||||||
return $parser->parseDocument();
|
return $parser->parseDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
|
* Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
|
||||||
* that value.
|
* that value.
|
||||||
* Throws GraphQL\Error\SyntaxError if a syntax error is encountered.
|
* Throws `GraphQL\Error\SyntaxError` if a syntax error is encountered.
|
||||||
*
|
*
|
||||||
* This is useful within tools that operate upon GraphQL Values directly and
|
* This is useful within tools that operate upon GraphQL Values directly and
|
||||||
* in isolation of complete GraphQL documents.
|
* in isolation of complete GraphQL documents.
|
||||||
*
|
*
|
||||||
* Consider providing the results to the utility function: GraphQL\Utils\AST::valueFromAST().
|
* Consider providing the results to the utility function: `GraphQL\Utils\AST::valueFromAST()`.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Source|string $source
|
* @param Source|string $source
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return BooleanValueNode|EnumValueNode|FloatValueNode|IntValueNode|ListValueNode|ObjectValueNode|StringValueNode|VariableNode
|
* @return BooleanValueNode|EnumValueNode|FloatValueNode|IntValueNode|ListValueNode|ObjectValueNode|StringValueNode|VariableNode
|
||||||
@ -94,13 +99,14 @@ class Parser
|
|||||||
/**
|
/**
|
||||||
* Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for
|
* Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for
|
||||||
* that type.
|
* that type.
|
||||||
* Throws GraphQL\Error\SyntaxError if a syntax error is encountered.
|
* Throws `GraphQL\Error\SyntaxError` if a syntax error is encountered.
|
||||||
*
|
*
|
||||||
* This is useful within tools that operate upon GraphQL Types directly and
|
* This is useful within tools that operate upon GraphQL Types directly and
|
||||||
* in isolation of complete GraphQL documents.
|
* in isolation of complete GraphQL documents.
|
||||||
*
|
*
|
||||||
* Consider providing the results to the utility function: GraphQL\Utils\AST::typeFromAST().
|
* Consider providing the results to the utility function: `GraphQL\Utils\AST::typeFromAST()`.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Source|string $source
|
* @param Source|string $source
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return ListTypeNode|NameNode|NonNullTypeNode
|
* @return ListTypeNode|NameNode|NonNullTypeNode
|
||||||
|
@ -40,11 +40,24 @@ use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
|||||||
use GraphQL\Language\AST\VariableDefinitionNode;
|
use GraphQL\Language\AST\VariableDefinitionNode;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints AST to string. Capable of printing GraphQL queries and Type definition language.
|
||||||
|
* Useful for pretty-printing queries or printing back AST for logging, documentation, etc.
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* ```php
|
||||||
|
* $query = 'query myQuery {someField}';
|
||||||
|
* $ast = GraphQL\Language\Parser::parse($query);
|
||||||
|
* $printed = GraphQL\Language\Printer::doPrint($ast);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
class Printer
|
class Printer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Prints AST to string. Capable of printing GraphQL queries and Type definition language.
|
* Prints AST to string. Capable of printing GraphQL queries and Type definition language.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Node $ast
|
* @param Node $ast
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -15,44 +15,95 @@ class VisitorOperation
|
|||||||
public $removeNode;
|
public $removeNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility for efficient AST traversal and modification.
|
||||||
|
*
|
||||||
|
* `visit()` will walk through an AST using a depth first traversal, calling
|
||||||
|
* the visitor's enter function at each node in the traversal, and calling the
|
||||||
|
* leave function after visiting that node and all of it's child nodes.
|
||||||
|
*
|
||||||
|
* By returning different values from the enter and leave functions, the
|
||||||
|
* behavior of the visitor can be altered, including skipping over a sub-tree of
|
||||||
|
* the AST (by returning false), editing the AST by returning a value or null
|
||||||
|
* to remove the value, or to stop the whole traversal by returning BREAK.
|
||||||
|
*
|
||||||
|
* When using `visit()` to edit an AST, the original AST will not be modified, and
|
||||||
|
* a new version of the AST with the changes applied will be returned from the
|
||||||
|
* visit function.
|
||||||
|
*
|
||||||
|
* $editedAST = Visitor::visit($ast, [
|
||||||
|
* 'enter' => function ($node, $key, $parent, $path, $ancestors) {
|
||||||
|
* // return
|
||||||
|
* // null: no action
|
||||||
|
* // Visitor::skipNode(): skip visiting this node
|
||||||
|
* // Visitor::stop(): stop visiting altogether
|
||||||
|
* // Visitor::removeNode(): delete this node
|
||||||
|
* // any value: replace this node with the returned value
|
||||||
|
* },
|
||||||
|
* 'leave' => function ($node, $key, $parent, $path, $ancestors) {
|
||||||
|
* // return
|
||||||
|
* // null: no action
|
||||||
|
* // Visitor::stop(): stop visiting altogether
|
||||||
|
* // Visitor::removeNode(): delete this node
|
||||||
|
* // any value: replace this node with the returned value
|
||||||
|
* }
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* Alternatively to providing enter() and leave() functions, a visitor can
|
||||||
|
* instead provide functions named the same as the [kinds of AST nodes](reference/#graphqllanguageastnodekind),
|
||||||
|
* or enter/leave visitors at a named key, leading to four permutations of
|
||||||
|
* visitor API:
|
||||||
|
*
|
||||||
|
* 1) Named visitors triggered when entering a node a specific kind.
|
||||||
|
*
|
||||||
|
* Visitor::visit($ast, [
|
||||||
|
* 'Kind' => function ($node) {
|
||||||
|
* // enter the "Kind" node
|
||||||
|
* }
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* 2) Named visitors that trigger upon entering and leaving a node of
|
||||||
|
* a specific kind.
|
||||||
|
*
|
||||||
|
* Visitor::visit($ast, [
|
||||||
|
* 'Kind' => [
|
||||||
|
* 'enter' => function ($node) {
|
||||||
|
* // enter the "Kind" node
|
||||||
|
* }
|
||||||
|
* 'leave' => function ($node) {
|
||||||
|
* // leave the "Kind" node
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* 3) Generic visitors that trigger upon entering and leaving any node.
|
||||||
|
*
|
||||||
|
* Visitor::visit($ast, [
|
||||||
|
* 'enter' => function ($node) {
|
||||||
|
* // enter any node
|
||||||
|
* },
|
||||||
|
* 'leave' => function ($node) {
|
||||||
|
* // leave any node
|
||||||
|
* }
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* 4) Parallel visitors for entering and leaving nodes of a specific kind.
|
||||||
|
*
|
||||||
|
* Visitor::visit($ast, [
|
||||||
|
* 'enter' => [
|
||||||
|
* 'Kind' => function($node) {
|
||||||
|
* // enter the "Kind" node
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* 'leave' => [
|
||||||
|
* 'Kind' => function ($node) {
|
||||||
|
* // leave the "Kind" node
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* ]);
|
||||||
|
*/
|
||||||
class Visitor
|
class Visitor
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Returns marker for visitor break
|
|
||||||
*
|
|
||||||
* @return VisitorOperation
|
|
||||||
*/
|
|
||||||
public static function stop()
|
|
||||||
{
|
|
||||||
$r = new VisitorOperation();
|
|
||||||
$r->doBreak = true;
|
|
||||||
return $r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns marker for skipping current node
|
|
||||||
*
|
|
||||||
* @return VisitorOperation
|
|
||||||
*/
|
|
||||||
public static function skipNode()
|
|
||||||
{
|
|
||||||
$r = new VisitorOperation();
|
|
||||||
$r->doContinue = true;
|
|
||||||
return $r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns marker for removing a node
|
|
||||||
*
|
|
||||||
* @return VisitorOperation
|
|
||||||
*/
|
|
||||||
public static function removeNode()
|
|
||||||
{
|
|
||||||
$r = new VisitorOperation();
|
|
||||||
$r->removeNode = true;
|
|
||||||
return $r;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static $visitorKeys = [
|
public static $visitorKeys = [
|
||||||
NodeKind::NAME => [],
|
NodeKind::NAME => [],
|
||||||
NodeKind::DOCUMENT => ['definitions'],
|
NodeKind::DOCUMENT => ['definitions'],
|
||||||
@ -96,90 +147,9 @@ class Visitor
|
|||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* visit() will walk through an AST using a depth first traversal, calling
|
* Visit the AST (see class description for details)
|
||||||
* the visitor's enter function at each node in the traversal, and calling the
|
|
||||||
* leave function after visiting that node and all of it's child nodes.
|
|
||||||
*
|
|
||||||
* By returning different values from the enter and leave functions, the
|
|
||||||
* behavior of the visitor can be altered, including skipping over a sub-tree of
|
|
||||||
* the AST (by returning false), editing the AST by returning a value or null
|
|
||||||
* to remove the value, or to stop the whole traversal by returning BREAK.
|
|
||||||
*
|
|
||||||
* When using visit() to edit an AST, the original AST will not be modified, and
|
|
||||||
* a new version of the AST with the changes applied will be returned from the
|
|
||||||
* visit function.
|
|
||||||
*
|
|
||||||
* $editedAST = Visitor::visit($ast, [
|
|
||||||
* 'enter' => function ($node, $key, $parent, $path, $ancestors) {
|
|
||||||
* // return
|
|
||||||
* // null: no action
|
|
||||||
* // Visitor::skipNode(): skip visiting this node
|
|
||||||
* // Visitor::stop(): stop visiting altogether
|
|
||||||
* // Visitor::removeNode(): delete this node
|
|
||||||
* // any value: replace this node with the returned value
|
|
||||||
* },
|
|
||||||
* 'leave' => function ($node, $key, $parent, $path, $ancestors) {
|
|
||||||
* // return
|
|
||||||
* // null: no action
|
|
||||||
* // Visitor::stop(): stop visiting altogether
|
|
||||||
* // Visitor::removeNode(): delete this node
|
|
||||||
* // any value: replace this node with the returned value
|
|
||||||
* }
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* Alternatively to providing enter() and leave() functions, a visitor can
|
|
||||||
* instead provide functions named the same as the kinds of AST nodes, or
|
|
||||||
* enter/leave visitors at a named key, leading to four permutations of
|
|
||||||
* visitor API:
|
|
||||||
*
|
|
||||||
* 1) Named visitors triggered when entering a node a specific kind.
|
|
||||||
*
|
|
||||||
* Visitor::visit($ast, [
|
|
||||||
* 'Kind' => function ($node) {
|
|
||||||
* // enter the "Kind" node
|
|
||||||
* }
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* 2) Named visitors that trigger upon entering and leaving a node of
|
|
||||||
* a specific kind.
|
|
||||||
*
|
|
||||||
* Visitor::visit($ast, [
|
|
||||||
* 'Kind' => [
|
|
||||||
* 'enter' => function ($node) {
|
|
||||||
* // enter the "Kind" node
|
|
||||||
* }
|
|
||||||
* 'leave' => function ($node) {
|
|
||||||
* // leave the "Kind" node
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* 3) Generic visitors that trigger upon entering and leaving any node.
|
|
||||||
*
|
|
||||||
* Visitor::visit($ast, [
|
|
||||||
* 'enter' => function ($node) {
|
|
||||||
* // enter any node
|
|
||||||
* },
|
|
||||||
* 'leave' => function ($node) {
|
|
||||||
* // leave any node
|
|
||||||
* }
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* 4) Parallel visitors for entering and leaving nodes of a specific kind.
|
|
||||||
*
|
|
||||||
* Visitor::visit($ast, [
|
|
||||||
* 'enter' => [
|
|
||||||
* 'Kind' => function($node) {
|
|
||||||
* // enter the "Kind" node
|
|
||||||
* }
|
|
||||||
* },
|
|
||||||
* 'leave' => [
|
|
||||||
* 'Kind' => function ($node) {
|
|
||||||
* // leave the "Kind" node
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* ]);
|
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param Node $root
|
* @param Node $root
|
||||||
* @param array $visitor
|
* @param array $visitor
|
||||||
* @param array $keyMap
|
* @param array $keyMap
|
||||||
@ -335,6 +305,45 @@ class Visitor
|
|||||||
return $newRoot;
|
return $newRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns marker for visitor break
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return VisitorOperation
|
||||||
|
*/
|
||||||
|
public static function stop()
|
||||||
|
{
|
||||||
|
$r = new VisitorOperation();
|
||||||
|
$r->doBreak = true;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns marker for skipping current node
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return VisitorOperation
|
||||||
|
*/
|
||||||
|
public static function skipNode()
|
||||||
|
{
|
||||||
|
$r = new VisitorOperation();
|
||||||
|
$r->doContinue = true;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns marker for removing a node
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return VisitorOperation
|
||||||
|
*/
|
||||||
|
public static function removeNode()
|
||||||
|
{
|
||||||
|
$r = new VisitorOperation();
|
||||||
|
$r->removeNode = true;
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $visitors
|
* @param $visitors
|
||||||
* @return array
|
* @return array
|
||||||
|
@ -5,29 +5,6 @@ namespace GraphQL;
|
|||||||
/**
|
/**
|
||||||
* Schema Definition
|
* Schema Definition
|
||||||
*
|
*
|
||||||
* A Schema is created by supplying the root types of each type of operation:
|
|
||||||
* query, mutation (optional) and subscription (optional). A schema definition is
|
|
||||||
* then supplied to the validator and executor.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
|
||||||
* $schema = new GraphQL\Schema([
|
|
||||||
* 'query' => $MyAppQueryRootType,
|
|
||||||
* 'mutation' => $MyAppMutationRootType,
|
|
||||||
* ]);
|
|
||||||
*
|
|
||||||
* Note: If an array of `directives` are provided to GraphQL\Schema, that will be
|
|
||||||
* the exact list of directives represented and allowed. If `directives` is not
|
|
||||||
* provided then a default set of the specified directives (e.g. @include and
|
|
||||||
* @skip) will be used. If you wish to provide *additional* directives to these
|
|
||||||
* specified directives, you must explicitly declare them. Example:
|
|
||||||
*
|
|
||||||
* $mySchema = new GraphQL\Schema([
|
|
||||||
* ...
|
|
||||||
* 'directives' => array_merge(GraphQL::getInternalDirectives(), [ $myCustomDirective ]),
|
|
||||||
* ])
|
|
||||||
*
|
|
||||||
* @package GraphQL
|
|
||||||
* @deprecated moved to GraphQL\Type\Schema
|
* @deprecated moved to GraphQL\Type\Schema
|
||||||
*/
|
*/
|
||||||
class Schema extends \GraphQL\Type\Schema
|
class Schema extends \GraphQL\Type\Schema
|
||||||
|
@ -19,17 +19,152 @@ use Psr\Http\Message\ServerRequestInterface;
|
|||||||
use Psr\Http\Message\StreamInterface;
|
use Psr\Http\Message\StreamInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Helper
|
|
||||||
* Contains functionality that could be re-used by various server implementations
|
* Contains functionality that could be re-used by various server implementations
|
||||||
*
|
|
||||||
* @package GraphQL\Server
|
|
||||||
*/
|
*/
|
||||||
class Helper
|
class Helper
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses HTTP request using PHP globals and returns GraphQL OperationParams
|
||||||
|
* contained in this request. For batched requests it returns an array of OperationParams.
|
||||||
|
*
|
||||||
|
* This function does not check validity of these params
|
||||||
|
* (validation is performed separately in validateOperationParams() method).
|
||||||
|
*
|
||||||
|
* If $readRawBodyFn argument is not provided - will attempt to read raw request body
|
||||||
|
* from `php://input` stream.
|
||||||
|
*
|
||||||
|
* Internally it normalizes input to $method, $bodyParams and $queryParams and
|
||||||
|
* calls `parseRequestParams()` to produce actual return value.
|
||||||
|
*
|
||||||
|
* For PSR-7 request parsing use `parsePsrRequest()` instead.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param callable|null $readRawBodyFn
|
||||||
|
* @return OperationParams|OperationParams[]
|
||||||
|
* @throws RequestError
|
||||||
|
*/
|
||||||
|
public function parseHttpRequest(callable $readRawBodyFn = null)
|
||||||
|
{
|
||||||
|
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null;
|
||||||
|
$bodyParams = [];
|
||||||
|
$urlParams = $_GET;
|
||||||
|
|
||||||
|
if ($method === 'POST') {
|
||||||
|
$contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : null;
|
||||||
|
|
||||||
|
if (stripos($contentType, 'application/graphql') !== false) {
|
||||||
|
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
||||||
|
$bodyParams = ['query' => $rawBody ?: ''];
|
||||||
|
} else if (stripos($contentType, 'application/json') !== false) {
|
||||||
|
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
||||||
|
$bodyParams = json_decode($rawBody ?: '', true);
|
||||||
|
|
||||||
|
if (json_last_error()) {
|
||||||
|
throw new RequestError("Could not parse JSON: " . json_last_error_msg());
|
||||||
|
}
|
||||||
|
if (!is_array($bodyParams)) {
|
||||||
|
throw new RequestError(
|
||||||
|
"GraphQL Server expects JSON object or array, but got " .
|
||||||
|
Utils::printSafeJson($bodyParams)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (stripos($contentType, 'application/x-www-form-urlencoded') !== false) {
|
||||||
|
$bodyParams = $_POST;
|
||||||
|
} else if (null === $contentType) {
|
||||||
|
throw new RequestError('Missing "Content-Type" header');
|
||||||
|
} else {
|
||||||
|
throw new RequestError("Unexpected content type: " . Utils::printSafeJson($contentType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parseRequestParams($method, $bodyParams, $urlParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses normalized request params and returns instance of OperationParams
|
||||||
|
* or array of OperationParams in case of batch operation.
|
||||||
|
*
|
||||||
|
* Returned value is a suitable input for `executeOperation` or `executeBatch` (if array)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param string $method
|
||||||
|
* @param array $bodyParams
|
||||||
|
* @param array $queryParams
|
||||||
|
* @return OperationParams|OperationParams[]
|
||||||
|
* @throws RequestError
|
||||||
|
*/
|
||||||
|
public function parseRequestParams($method, array $bodyParams, array $queryParams)
|
||||||
|
{
|
||||||
|
if ($method === 'GET') {
|
||||||
|
$result = OperationParams::create($queryParams, true);
|
||||||
|
} else if ($method === 'POST') {
|
||||||
|
if (isset($bodyParams[0])) {
|
||||||
|
$result = [];
|
||||||
|
foreach ($bodyParams as $index => $entry) {
|
||||||
|
$op = OperationParams::create($entry);
|
||||||
|
$result[] = $op;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$result = OperationParams::create($bodyParams);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RequestError('HTTP Method "' . $method . '" is not supported');
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks validity of OperationParams extracted from HTTP request and returns an array of errors
|
||||||
|
* if params are invalid (or empty array when params are valid)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param OperationParams $params
|
||||||
|
* @return Error[]
|
||||||
|
*/
|
||||||
|
public function validateOperationParams(OperationParams $params)
|
||||||
|
{
|
||||||
|
$errors = [];
|
||||||
|
if (!$params->query && !$params->queryId) {
|
||||||
|
$errors[] = new RequestError('GraphQL Request must include at least one of those two parameters: "query" or "queryId"');
|
||||||
|
}
|
||||||
|
if ($params->query && $params->queryId) {
|
||||||
|
$errors[] = new RequestError('GraphQL Request parameters "query" and "queryId" are mutually exclusive');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($params->query !== null && (!is_string($params->query) || empty($params->query))) {
|
||||||
|
$errors[] = new RequestError(
|
||||||
|
'GraphQL Request parameter "query" must be string, but got ' .
|
||||||
|
Utils::printSafeJson($params->query)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($params->queryId !== null && (!is_string($params->queryId) || empty($params->queryId))) {
|
||||||
|
$errors[] = new RequestError(
|
||||||
|
'GraphQL Request parameter "queryId" must be string, but got ' .
|
||||||
|
Utils::printSafeJson($params->queryId)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($params->operation !== null && (!is_string($params->operation) || empty($params->operation))) {
|
||||||
|
$errors[] = new RequestError(
|
||||||
|
'GraphQL Request parameter "operation" must be string, but got ' .
|
||||||
|
Utils::printSafeJson($params->operation)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ($params->variables !== null && (!is_array($params->variables) || isset($params->variables[0]))) {
|
||||||
|
$errors[] = new RequestError(
|
||||||
|
'GraphQL Request parameter "variables" must be object or JSON string parsed to object, but got ' .
|
||||||
|
Utils::printSafeJson($params->getOriginalInput('variables'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes GraphQL operation with given server configuration and returns execution result
|
* Executes GraphQL operation with given server configuration and returns execution result
|
||||||
* (or promise when promise adapter is different than SyncPromiseAdapter)
|
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param ServerConfig $config
|
* @param ServerConfig $config
|
||||||
* @param OperationParams $op
|
* @param OperationParams $op
|
||||||
*
|
*
|
||||||
@ -51,6 +186,7 @@ class Helper
|
|||||||
* Executes batched GraphQL operations with shared promise queue
|
* Executes batched GraphQL operations with shared promise queue
|
||||||
* (thus, effectively batching deferreds|promises of all queries at once)
|
* (thus, effectively batching deferreds|promises of all queries at once)
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param ServerConfig $config
|
* @param ServerConfig $config
|
||||||
* @param OperationParams[] $operations
|
* @param OperationParams[] $operations
|
||||||
* @return ExecutionResult[]|Promise
|
* @return ExecutionResult[]|Promise
|
||||||
@ -241,138 +377,9 @@ class Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses HTTP request and returns GraphQL OperationParams contained in this request.
|
* Send response using standard PHP `header()` and `echo`.
|
||||||
* For batched requests it returns an array of OperationParams.
|
|
||||||
*
|
*
|
||||||
* This function doesn't check validity of these params.
|
* @api
|
||||||
*
|
|
||||||
* If $readRawBodyFn argument is not provided - will attempt to read raw request body from php://input stream
|
|
||||||
*
|
|
||||||
* @param callable|null $readRawBodyFn
|
|
||||||
* @return OperationParams|OperationParams[]
|
|
||||||
* @throws RequestError
|
|
||||||
*/
|
|
||||||
public function parseHttpRequest(callable $readRawBodyFn = null)
|
|
||||||
{
|
|
||||||
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : null;
|
|
||||||
$bodyParams = [];
|
|
||||||
$urlParams = $_GET;
|
|
||||||
|
|
||||||
if ($method === 'POST') {
|
|
||||||
$contentType = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : null;
|
|
||||||
|
|
||||||
if (stripos($contentType, 'application/graphql') !== false) {
|
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
|
||||||
$bodyParams = ['query' => $rawBody ?: ''];
|
|
||||||
} else if (stripos($contentType, 'application/json') !== false) {
|
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
|
||||||
$bodyParams = json_decode($rawBody ?: '', true);
|
|
||||||
|
|
||||||
if (json_last_error()) {
|
|
||||||
throw new RequestError("Could not parse JSON: " . json_last_error_msg());
|
|
||||||
}
|
|
||||||
if (!is_array($bodyParams)) {
|
|
||||||
throw new RequestError(
|
|
||||||
"GraphQL Server expects JSON object or array, but got " .
|
|
||||||
Utils::printSafeJson($bodyParams)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (stripos($contentType, 'application/x-www-form-urlencoded') !== false) {
|
|
||||||
$bodyParams = $_POST;
|
|
||||||
} else if (null === $contentType) {
|
|
||||||
throw new RequestError('Missing "Content-Type" header');
|
|
||||||
} else {
|
|
||||||
throw new RequestError("Unexpected content type: " . Utils::printSafeJson($contentType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->parseRequestParams($method, $bodyParams, $urlParams);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts PSR7 request to OperationParams[]
|
|
||||||
*
|
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @return array|Helper
|
|
||||||
* @throws RequestError
|
|
||||||
*/
|
|
||||||
public function parsePsrRequest(ServerRequestInterface $request)
|
|
||||||
{
|
|
||||||
if ($request->getMethod() === 'GET') {
|
|
||||||
$bodyParams = [];
|
|
||||||
} else {
|
|
||||||
$contentType = $request->getHeader('content-type');
|
|
||||||
|
|
||||||
if (!isset($contentType[0])) {
|
|
||||||
throw new RequestError('Missing "Content-Type" header');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stripos('application/graphql', $contentType[0]) !== false) {
|
|
||||||
$bodyParams = ['query' => $request->getBody()->getContents()];
|
|
||||||
} else if (stripos('application/json', $contentType[0]) !== false) {
|
|
||||||
$bodyParams = $request->getParsedBody();
|
|
||||||
|
|
||||||
if (null === $bodyParams) {
|
|
||||||
throw new InvariantViolation(
|
|
||||||
"PSR request is expected to provide parsed body for \"application/json\" requests but got null"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_array($bodyParams)) {
|
|
||||||
throw new RequestError(
|
|
||||||
"GraphQL Server expects JSON object or array, but got " .
|
|
||||||
Utils::printSafeJson($bodyParams)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$bodyParams = $request->getParsedBody();
|
|
||||||
|
|
||||||
if (!is_array($bodyParams)) {
|
|
||||||
throw new RequestError("Unexpected content type: " . Utils::printSafeJson($contentType[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->parseRequestParams(
|
|
||||||
$request->getMethod(),
|
|
||||||
$bodyParams,
|
|
||||||
$request->getQueryParams()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts query execution result to PSR response
|
|
||||||
*
|
|
||||||
* @param Promise|ExecutionResult|ExecutionResult[] $result
|
|
||||||
* @param ResponseInterface $response
|
|
||||||
* @param StreamInterface $writableBodyStream
|
|
||||||
* @return Promise|ResponseInterface
|
|
||||||
*/
|
|
||||||
public function toPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
|
|
||||||
{
|
|
||||||
if ($result instanceof Promise) {
|
|
||||||
return $result->then(function($actualResult) use ($response, $writableBodyStream) {
|
|
||||||
return $this->doConvertToPsrResponse($actualResult, $response, $writableBodyStream);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return $this->doConvertToPsrResponse($result, $response, $writableBodyStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function doConvertToPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
|
|
||||||
{
|
|
||||||
$httpStatus = $this->resolveHttpStatus($result);
|
|
||||||
|
|
||||||
$result = json_encode($result);
|
|
||||||
$writableBodyStream->write($result);
|
|
||||||
|
|
||||||
return $response
|
|
||||||
->withStatus($httpStatus)
|
|
||||||
->withHeader('Content-Type', 'application/json')
|
|
||||||
->withBody($writableBodyStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Promise|ExecutionResult|ExecutionResult[] $result
|
* @param Promise|ExecutionResult|ExecutionResult[] $result
|
||||||
* @param bool $exitWhenDone
|
* @param bool $exitWhenDone
|
||||||
*/
|
*/
|
||||||
@ -404,38 +411,6 @@ class Helper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses normalized request params and returns instance of OperationParams or array of OperationParams in
|
|
||||||
* case of batch operation.
|
|
||||||
*
|
|
||||||
* Returned value is a suitable input for `executeOperation` or `executeBatch` (if array)
|
|
||||||
*
|
|
||||||
* @param string $method
|
|
||||||
* @param array $bodyParams
|
|
||||||
* @param array $queryParams
|
|
||||||
* @return OperationParams|OperationParams[]
|
|
||||||
* @throws RequestError
|
|
||||||
*/
|
|
||||||
public function parseRequestParams($method, array $bodyParams, array $queryParams)
|
|
||||||
{
|
|
||||||
if ($method === 'GET') {
|
|
||||||
$result = OperationParams::create($queryParams, true);
|
|
||||||
} else if ($method === 'POST') {
|
|
||||||
if (isset($bodyParams[0])) {
|
|
||||||
$result = [];
|
|
||||||
foreach ($bodyParams as $index => $entry) {
|
|
||||||
$op = OperationParams::create($entry);
|
|
||||||
$result[] = $op;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$result = OperationParams::create($bodyParams);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new RequestError('HTTP Method "' . $method . '" is not supported');
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool|string
|
* @return bool|string
|
||||||
*/
|
*/
|
||||||
@ -444,50 +419,6 @@ class Helper
|
|||||||
return file_get_contents('php://input');
|
return file_get_contents('php://input');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks validity of operation params and returns array of errors (empty array when params are valid)
|
|
||||||
*
|
|
||||||
* @param OperationParams $params
|
|
||||||
* @return Error[]
|
|
||||||
*/
|
|
||||||
public function validateOperationParams(OperationParams $params)
|
|
||||||
{
|
|
||||||
$errors = [];
|
|
||||||
if (!$params->query && !$params->queryId) {
|
|
||||||
$errors[] = new RequestError('GraphQL Request must include at least one of those two parameters: "query" or "queryId"');
|
|
||||||
}
|
|
||||||
if ($params->query && $params->queryId) {
|
|
||||||
$errors[] = new RequestError('GraphQL Request parameters "query" and "queryId" are mutually exclusive');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params->query !== null && (!is_string($params->query) || empty($params->query))) {
|
|
||||||
$errors[] = new RequestError(
|
|
||||||
'GraphQL Request parameter "query" must be string, but got ' .
|
|
||||||
Utils::printSafeJson($params->query)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($params->queryId !== null && (!is_string($params->queryId) || empty($params->queryId))) {
|
|
||||||
$errors[] = new RequestError(
|
|
||||||
'GraphQL Request parameter "queryId" must be string, but got ' .
|
|
||||||
Utils::printSafeJson($params->queryId)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($params->operation !== null && (!is_string($params->operation) || empty($params->operation))) {
|
|
||||||
$errors[] = new RequestError(
|
|
||||||
'GraphQL Request parameter "operation" must be string, but got ' .
|
|
||||||
Utils::printSafeJson($params->operation)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ($params->variables !== null && (!is_array($params->variables) || isset($params->variables[0]))) {
|
|
||||||
$errors[] = new RequestError(
|
|
||||||
'GraphQL Request parameter "variables" must be object or JSON string parsed to object, but got ' .
|
|
||||||
Utils::printSafeJson($params->getOriginalInput('variables'))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return $errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $result
|
* @param $result
|
||||||
* @return int
|
* @return int
|
||||||
@ -522,4 +453,89 @@ class Helper
|
|||||||
}
|
}
|
||||||
return $httpStatus;
|
return $httpStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts PSR-7 request to OperationParams[]
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return array|Helper
|
||||||
|
* @throws RequestError
|
||||||
|
*/
|
||||||
|
public function parsePsrRequest(ServerRequestInterface $request)
|
||||||
|
{
|
||||||
|
if ($request->getMethod() === 'GET') {
|
||||||
|
$bodyParams = [];
|
||||||
|
} else {
|
||||||
|
$contentType = $request->getHeader('content-type');
|
||||||
|
|
||||||
|
if (!isset($contentType[0])) {
|
||||||
|
throw new RequestError('Missing "Content-Type" header');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stripos('application/graphql', $contentType[0]) !== false) {
|
||||||
|
$bodyParams = ['query' => $request->getBody()->getContents()];
|
||||||
|
} else if (stripos('application/json', $contentType[0]) !== false) {
|
||||||
|
$bodyParams = $request->getParsedBody();
|
||||||
|
|
||||||
|
if (null === $bodyParams) {
|
||||||
|
throw new InvariantViolation(
|
||||||
|
"PSR-7 request is expected to provide parsed body for \"application/json\" requests but got null"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($bodyParams)) {
|
||||||
|
throw new RequestError(
|
||||||
|
"GraphQL Server expects JSON object or array, but got " .
|
||||||
|
Utils::printSafeJson($bodyParams)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$bodyParams = $request->getParsedBody();
|
||||||
|
|
||||||
|
if (!is_array($bodyParams)) {
|
||||||
|
throw new RequestError("Unexpected content type: " . Utils::printSafeJson($contentType[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->parseRequestParams(
|
||||||
|
$request->getMethod(),
|
||||||
|
$bodyParams,
|
||||||
|
$request->getQueryParams()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts query execution result to PSR-7 response
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param Promise|ExecutionResult|ExecutionResult[] $result
|
||||||
|
* @param ResponseInterface $response
|
||||||
|
* @param StreamInterface $writableBodyStream
|
||||||
|
* @return Promise|ResponseInterface
|
||||||
|
*/
|
||||||
|
public function toPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
|
||||||
|
{
|
||||||
|
if ($result instanceof Promise) {
|
||||||
|
return $result->then(function($actualResult) use ($response, $writableBodyStream) {
|
||||||
|
return $this->doConvertToPsrResponse($actualResult, $response, $writableBodyStream);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return $this->doConvertToPsrResponse($result, $response, $writableBodyStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function doConvertToPsrResponse($result, ResponseInterface $response, StreamInterface $writableBodyStream)
|
||||||
|
{
|
||||||
|
$httpStatus = $this->resolveHttpStatus($result);
|
||||||
|
|
||||||
|
$result = json_encode($result);
|
||||||
|
$writableBodyStream->write($result);
|
||||||
|
|
||||||
|
return $response
|
||||||
|
->withStatus($httpStatus)
|
||||||
|
->withHeader('Content-Type', 'application/json')
|
||||||
|
->withBody($writableBodyStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,29 +2,37 @@
|
|||||||
namespace GraphQL\Server;
|
namespace GraphQL\Server;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class QueryParams
|
* Structure representing parsed HTTP parameters for GraphQL operation
|
||||||
* Represents all available parsed query parameters
|
|
||||||
*
|
|
||||||
* @package GraphQL\Server
|
|
||||||
*/
|
*/
|
||||||
class OperationParams
|
class OperationParams
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* Id of the query (when using persistent queries).
|
||||||
*/
|
*
|
||||||
public $query;
|
* Valid aliases (case-insensitive):
|
||||||
|
* - id
|
||||||
/**
|
* - queryId
|
||||||
|
* - documentId
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $queryId;
|
public $queryId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public $query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $operation;
|
public $operation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $variables;
|
public $variables;
|
||||||
@ -42,10 +50,10 @@ class OperationParams
|
|||||||
/**
|
/**
|
||||||
* Creates an instance from given array
|
* Creates an instance from given array
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param array $params
|
* @param array $params
|
||||||
* @param bool $readonly
|
* @param bool $readonly
|
||||||
*
|
* @return OperationParams
|
||||||
* @return static
|
|
||||||
*/
|
*/
|
||||||
public static function create(array $params, $readonly = false)
|
public static function create(array $params, $readonly = false)
|
||||||
{
|
{
|
||||||
@ -80,6 +88,7 @@ class OperationParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
@ -89,6 +98,10 @@ class OperationParams
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Indicates that operation is executed in read-only context
|
||||||
|
* (e.g. via HTTP GET request)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isReadOnly()
|
public function isReadOnly()
|
||||||
|
@ -6,10 +6,28 @@ use GraphQL\Executor\Promise\PromiseAdapter;
|
|||||||
use GraphQL\Type\Schema;
|
use GraphQL\Type\Schema;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server configuration class.
|
||||||
|
* Could be passed directly to server constructor. List of options accepted by **create** method is
|
||||||
|
* [described in docs](executing-queries/#server-configuration-options).
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* $config = GraphQL\Server\ServerConfig::create()
|
||||||
|
* ->setSchema($mySchema)
|
||||||
|
* ->setContext($myContext);
|
||||||
|
*
|
||||||
|
* $server = new GraphQL\Server\StandardServer($config);
|
||||||
|
*/
|
||||||
class ServerConfig
|
class ServerConfig
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @return static
|
* Converts an array of options to instance of ServerConfig
|
||||||
|
* (or just returns empty config when array is not passed).
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param array $config
|
||||||
|
* @return ServerConfig
|
||||||
*/
|
*/
|
||||||
public static function create(array $config = [])
|
public static function create(array $config = [])
|
||||||
{
|
{
|
||||||
@ -80,14 +98,18 @@ class ServerConfig
|
|||||||
private $persistentQueryLoader;
|
private $persistentQueryLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed|callable
|
* @api
|
||||||
|
* @param Schema $schema
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function getContext()
|
public function setSchema(Schema $schema)
|
||||||
{
|
{
|
||||||
return $this->context;
|
$this->schema = $schema;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param mixed|\Closure $context
|
* @param mixed|\Closure $context
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -98,6 +120,7 @@ class ServerConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param mixed|\Closure $rootValue
|
* @param mixed|\Closure $rootValue
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
@ -107,6 +130,123 @@ class ServerConfig
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expects function(Throwable $e) : array
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param callable $errorFormatter
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setErrorFormatter(callable $errorFormatter)
|
||||||
|
{
|
||||||
|
$this->errorFormatter = $errorFormatter;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expects function(array $errors, callable $formatter) : array
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param callable $handler
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setErrorsHandler(callable $handler)
|
||||||
|
{
|
||||||
|
$this->errorsHandler = $handler;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set validation rules for this server.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param array|callable
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setValidationRules($validationRules)
|
||||||
|
{
|
||||||
|
if (!is_callable($validationRules) && !is_array($validationRules) && $validationRules !== null) {
|
||||||
|
throw new InvariantViolation(
|
||||||
|
'Server config expects array of validation rules or callable returning such array, but got ' .
|
||||||
|
Utils::printSafe($validationRules)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->validationRules = $validationRules;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @param callable $fieldResolver
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setFieldResolver(callable $fieldResolver)
|
||||||
|
{
|
||||||
|
$this->fieldResolver = $fieldResolver;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expects function($queryId, OperationParams $params) : string|DocumentNode
|
||||||
|
*
|
||||||
|
* This function must return query string or valid DocumentNode.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param callable $persistentQueryLoader
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setPersistentQueryLoader(callable $persistentQueryLoader)
|
||||||
|
{
|
||||||
|
$this->persistentQueryLoader = $persistentQueryLoader;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set response debug flags. See GraphQL\Error\Debug class for a list of all available flags
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param bool|int $set
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setDebug($set = true)
|
||||||
|
{
|
||||||
|
$this->debug = $set;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow batching queries (disabled by default)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param bool $enableBatching
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setQueryBatching($enableBatching)
|
||||||
|
{
|
||||||
|
$this->queryBatching = (bool) $enableBatching;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @param PromiseAdapter $promiseAdapter
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setPromiseAdapter(PromiseAdapter $promiseAdapter)
|
||||||
|
{
|
||||||
|
$this->promiseAdapter = $promiseAdapter;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed|callable
|
||||||
|
*/
|
||||||
|
public function getContext()
|
||||||
|
{
|
||||||
|
return $this->context;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed|callable
|
* @return mixed|callable
|
||||||
*/
|
*/
|
||||||
@ -115,18 +255,6 @@ class ServerConfig
|
|||||||
return $this->rootValue;
|
return $this->rootValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set schema instance
|
|
||||||
*
|
|
||||||
* @param Schema $schema
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setSchema(Schema $schema)
|
|
||||||
{
|
|
||||||
$this->schema = $schema;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Schema
|
* @return Schema
|
||||||
*/
|
*/
|
||||||
@ -143,30 +271,6 @@ class ServerConfig
|
|||||||
return $this->errorFormatter;
|
return $this->errorFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Expects function(Throwable $e) : array
|
|
||||||
*
|
|
||||||
* @param callable $errorFormatter
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setErrorFormatter(callable $errorFormatter)
|
|
||||||
{
|
|
||||||
$this->errorFormatter = $errorFormatter;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expects function(array $errors, callable $formatter) : array
|
|
||||||
*
|
|
||||||
* @param callable $handler
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setErrorsHandler(callable $handler)
|
|
||||||
{
|
|
||||||
$this->errorsHandler = $handler;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return callable|null
|
* @return callable|null
|
||||||
*/
|
*/
|
||||||
@ -183,16 +287,6 @@ class ServerConfig
|
|||||||
return $this->promiseAdapter;
|
return $this->promiseAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param PromiseAdapter $promiseAdapter
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setPromiseAdapter(PromiseAdapter $promiseAdapter)
|
|
||||||
{
|
|
||||||
$this->promiseAdapter = $promiseAdapter;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array|callable
|
* @return array|callable
|
||||||
*/
|
*/
|
||||||
@ -201,25 +295,6 @@ class ServerConfig
|
|||||||
return $this->validationRules;
|
return $this->validationRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set validation rules for this server.
|
|
||||||
*
|
|
||||||
* @param array|callable
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setValidationRules($validationRules)
|
|
||||||
{
|
|
||||||
if (!is_callable($validationRules) && !is_array($validationRules) && $validationRules !== null) {
|
|
||||||
throw new InvariantViolation(
|
|
||||||
'Server config expects array of validation rules or callable returning such array, but got ' .
|
|
||||||
Utils::printSafe($validationRules)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->validationRules = $validationRules;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return callable
|
* @return callable
|
||||||
*/
|
*/
|
||||||
@ -228,16 +303,6 @@ class ServerConfig
|
|||||||
return $this->fieldResolver;
|
return $this->fieldResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $fieldResolver
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setFieldResolver(callable $fieldResolver)
|
|
||||||
{
|
|
||||||
$this->fieldResolver = $fieldResolver;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return callable
|
* @return callable
|
||||||
*/
|
*/
|
||||||
@ -246,19 +311,6 @@ class ServerConfig
|
|||||||
return $this->persistentQueryLoader;
|
return $this->persistentQueryLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A function that takes an input id and returns a valid Document.
|
|
||||||
* If provided, this will allow your GraphQL endpoint to execute a document specified via `queryId`.
|
|
||||||
*
|
|
||||||
* @param callable $persistentQueryLoader
|
|
||||||
* @return ServerConfig
|
|
||||||
*/
|
|
||||||
public function setPersistentQueryLoader(callable $persistentQueryLoader)
|
|
||||||
{
|
|
||||||
$this->persistentQueryLoader = $persistentQueryLoader;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@ -267,18 +319,6 @@ class ServerConfig
|
|||||||
return $this->debug;
|
return $this->debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set response debug flags, see GraphQL\Error\Debug class for a list of available flags
|
|
||||||
*
|
|
||||||
* @param bool|int $set
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setDebug($set = true)
|
|
||||||
{
|
|
||||||
$this->debug = $set;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@ -286,16 +326,4 @@ class ServerConfig
|
|||||||
{
|
{
|
||||||
return $this->queryBatching;
|
return $this->queryBatching;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow batching queries
|
|
||||||
*
|
|
||||||
* @param bool $enableBatching
|
|
||||||
* @return ServerConfig
|
|
||||||
*/
|
|
||||||
public function setQueryBatching($enableBatching)
|
|
||||||
{
|
|
||||||
$this->queryBatching = (bool) $enableBatching;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,26 @@ use Psr\Http\Message\ServerRequestInterface;
|
|||||||
use Psr\Http\Message\StreamInterface;
|
use Psr\Http\Message\StreamInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StandardServer
|
* GraphQL server compatible with both: [express-graphql](https://github.com/graphql/express-graphql)
|
||||||
|
* and [Apollo Server](https://github.com/apollographql/graphql-server).
|
||||||
|
* Usage Example:
|
||||||
*
|
*
|
||||||
* GraphQL server compatible with both:
|
* $server = new StandardServer([
|
||||||
* https://github.com/graphql/express-graphql and https://github.com/apollographql/graphql-server
|
* 'schema' => $mySchema
|
||||||
|
* ]);
|
||||||
|
* $server->handleRequest();
|
||||||
|
*
|
||||||
|
* Or using [ServerConfig](reference/#graphqlserverserverconfig) instance:
|
||||||
|
*
|
||||||
|
* $config = GraphQL\Server\ServerConfig::create()
|
||||||
|
* ->setSchema($mySchema)
|
||||||
|
* ->setContext($myContext);
|
||||||
|
*
|
||||||
|
* $server = new GraphQL\Server\StandardServer($config);
|
||||||
|
* $server->handleRequest();
|
||||||
|
*
|
||||||
|
* See [dedicated section in docs](executing-queries/#using-server) for details.
|
||||||
*
|
*
|
||||||
* @package GraphQL\Server
|
|
||||||
*/
|
*/
|
||||||
class StandardServer
|
class StandardServer
|
||||||
{
|
{
|
||||||
@ -30,8 +44,9 @@ class StandardServer
|
|||||||
private $helper;
|
private $helper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard GraphQL HTTP server implementation
|
* Creates new instance of a standard GraphQL HTTP server
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param ServerConfig|array $config
|
* @param ServerConfig|array $config
|
||||||
*/
|
*/
|
||||||
public function __construct($config)
|
public function __construct($config)
|
||||||
@ -46,22 +61,36 @@ class StandardServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes GraphQL operation with given server configuration and returns execution result
|
* Parses HTTP request, executes and emits response (using standard PHP `header` function and `echo`)
|
||||||
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
|
||||||
*
|
*
|
||||||
* @param ServerRequestInterface $request
|
* By default (when $parsedBody is not set) it uses PHP globals to parse a request.
|
||||||
* @return ExecutionResult|ExecutionResult[]|Promise
|
* It is possible to implement request parsing elsewhere (e.g. using framework Request instance)
|
||||||
|
* and then pass it to the server.
|
||||||
|
*
|
||||||
|
* See `executeRequest()` if you prefer to emit response yourself
|
||||||
|
* (e.g. using Response object of some framework)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param OperationParams|OperationParams[] $parsedBody
|
||||||
|
* @param bool $exitWhenDone
|
||||||
*/
|
*/
|
||||||
public function executePsrRequest(ServerRequestInterface $request)
|
public function handleRequest($parsedBody = null, $exitWhenDone = false)
|
||||||
{
|
{
|
||||||
$parsedBody = $this->helper->parsePsrRequest($request);
|
$result = $this->executeRequest($parsedBody);
|
||||||
return $this->executeRequest($parsedBody);
|
$this->helper->sendResponse($result, $exitWhenDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes GraphQL operation with given server configuration and returns execution result
|
* Executes GraphQL operation and returns execution result
|
||||||
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
* (or promise when promise adapter is different from SyncPromiseAdapter).
|
||||||
*
|
*
|
||||||
|
* By default (when $parsedBody is not set) it uses PHP globals to parse a request.
|
||||||
|
* It is possible to implement request parsing elsewhere (e.g. using framework Request instance)
|
||||||
|
* and then pass it to the server.
|
||||||
|
*
|
||||||
|
* PSR-7 compatible method executePsrRequest() does exactly this.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param OperationParams|OperationParams[] $parsedBody
|
* @param OperationParams|OperationParams[] $parsedBody
|
||||||
* @return ExecutionResult|ExecutionResult[]|Promise
|
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||||
* @throws InvariantViolation
|
* @throws InvariantViolation
|
||||||
@ -79,7 +108,13 @@ class StandardServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Executes PSR-7 request and fulfills PSR-7 response.
|
||||||
|
*
|
||||||
|
* See `executePsrRequest()` if you prefer to create response yourself
|
||||||
|
* (e.g. using specific JsonResponse instance of some framework).
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param ServerRequestInterface $request
|
* @param ServerRequestInterface $request
|
||||||
* @param ResponseInterface $response
|
* @param ResponseInterface $response
|
||||||
* @param StreamInterface $writableBodyStream
|
* @param StreamInterface $writableBodyStream
|
||||||
@ -96,12 +131,28 @@ class StandardServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OperationParams|OperationParams[] $parsedBody
|
* Executes GraphQL operation and returns execution result
|
||||||
* @param bool $exitWhenDone
|
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||||
*/
|
*/
|
||||||
public function handleRequest($parsedBody = null, $exitWhenDone = false)
|
public function executePsrRequest(ServerRequestInterface $request)
|
||||||
{
|
{
|
||||||
$result = $this->executeRequest($parsedBody);
|
$parsedBody = $this->helper->parsePsrRequest($request);
|
||||||
$this->helper->sendResponse($result, $exitWhenDone);
|
return $this->executeRequest($parsedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of Server helper, which contains most of the actual logic for
|
||||||
|
* parsing / validating / executing request (which could be re-used by other server implementations)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return Helper
|
||||||
|
*/
|
||||||
|
public function getHelper()
|
||||||
|
{
|
||||||
|
return $this->helper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ class Config
|
|||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
'GraphQL\Type\Defintion\Config is deprecated and will be removed in the next version. ' .
|
'GraphQL\Type\Defintion\Config is deprecated and will be removed in the next version. ' .
|
||||||
'See https://github.com/webonyx/graphql-php/issues/148 for alternatives',
|
'See https://github.com/webonyx/graphql-php/issues/148 for alternatives',
|
||||||
Warning::CONFIG_DEPRECATION_WARNING,
|
Warning::WARNING_CONFIG_DEPRECATION,
|
||||||
E_USER_DEPRECATED
|
E_USER_DEPRECATED
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ class Config
|
|||||||
if (!self::$allowCustomOptions) {
|
if (!self::$allowCustomOptions) {
|
||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
sprintf('Error in "%s" type definition: Non-standard keys "%s" ' . $suffix, $typeName, implode(', ', $unexpectedKeys)),
|
sprintf('Error in "%s" type definition: Non-standard keys "%s" ' . $suffix, $typeName, implode(', ', $unexpectedKeys)),
|
||||||
Warning::CONFIG_WARNING
|
Warning::WARNING_CONFIG
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$map = array_intersect_key($map, $definitions);
|
$map = array_intersect_key($map, $definitions);
|
||||||
|
@ -11,7 +11,7 @@ use GraphQL\Utils\Utils;
|
|||||||
class ListOfType extends Type implements WrappingType, OutputType, InputType
|
class ListOfType extends Type implements WrappingType, OutputType, InputType
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var callable|Type
|
* @var ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
*/
|
*/
|
||||||
public $ofType;
|
public $ofType;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $recurse
|
* @param bool $recurse
|
||||||
* @return mixed
|
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
*/
|
*/
|
||||||
public function getWrappedType($recurse = false)
|
public function getWrappedType($recurse = false)
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,7 @@ use GraphQL\Utils\Utils;
|
|||||||
class NonNull extends Type implements WrappingType, OutputType, InputType
|
class NonNull extends Type implements WrappingType, OutputType, InputType
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var callable|Type
|
* @var ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
*/
|
*/
|
||||||
private $ofType;
|
private $ofType;
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ class NonNull extends Type implements WrappingType, OutputType, InputType
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $recurse
|
* @param bool $recurse
|
||||||
* @return mixed
|
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
* @throws \Exception
|
* @throws InvariantViolation
|
||||||
*/
|
*/
|
||||||
public function getWrappedType($recurse = false)
|
public function getWrappedType($recurse = false)
|
||||||
{
|
{
|
||||||
|
@ -12,12 +12,15 @@ use GraphQL\Type\Schema;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class ResolveInfo
|
* Structure containing information useful for field resolution process.
|
||||||
* @package GraphQL\Type\Definition
|
* Passed as 3rd argument to every field resolver. See [docs on field resolving (data fetching)](data-fetching/).
|
||||||
*/
|
*/
|
||||||
class ResolveInfo
|
class ResolveInfo
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* The name of the field being resolved
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public $fieldName;
|
public $fieldName;
|
||||||
@ -29,47 +32,74 @@ class ResolveInfo
|
|||||||
public $fieldASTs;
|
public $fieldASTs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* AST of all nodes referencing this field in the query.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var FieldNode[]
|
* @var FieldNode[]
|
||||||
*/
|
*/
|
||||||
public $fieldNodes;
|
public $fieldNodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Expected return type of the field being resolved
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var ScalarType|ObjectType|InterfaceType|UnionType|EnumType|ListOfType|NonNull
|
* @var ScalarType|ObjectType|InterfaceType|UnionType|EnumType|ListOfType|NonNull
|
||||||
*/
|
*/
|
||||||
public $returnType;
|
public $returnType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ObjectType|InterfaceType|UnionType
|
* Parent type of the field being resolved
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @var ObjectType
|
||||||
*/
|
*/
|
||||||
public $parentType;
|
public $parentType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Path to this field from the very root value
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $path;
|
public $path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Instance of a schema used for execution
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var Schema
|
* @var Schema
|
||||||
*/
|
*/
|
||||||
public $schema;
|
public $schema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* AST of all fragments defined in query
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var FragmentDefinitionNode[]
|
* @var FragmentDefinitionNode[]
|
||||||
*/
|
*/
|
||||||
public $fragments;
|
public $fragments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Root value passed to query execution
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var mixed
|
* @var mixed
|
||||||
*/
|
*/
|
||||||
public $rootValue;
|
public $rootValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* AST of operation definition node (query, mutation)
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @var OperationDefinitionNode
|
* @var OperationDefinitionNode
|
||||||
*/
|
*/
|
||||||
public $operation;
|
public $operation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<variableName, mixed>
|
* Array of variables passed to query execution
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $variableValues;
|
public $variableValues;
|
||||||
|
|
||||||
@ -107,6 +137,10 @@ class ResolveInfo
|
|||||||
* ]
|
* ]
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
|
* Warning: this method it is a naive implementation which does not take into account
|
||||||
|
* conditional typed fragments. So use it with care for fields of interface and union types.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param int $depth How many levels to include in output
|
* @param int $depth How many levels to include in output
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -4,17 +4,12 @@ namespace GraphQL\Type\Definition;
|
|||||||
use GraphQL\Error\InvariantViolation;
|
use GraphQL\Error\InvariantViolation;
|
||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
export type GraphQLType =
|
* Registry of standard GraphQL types
|
||||||
GraphQLScalarType |
|
* and a base class for all other types.
|
||||||
GraphQLObjectType |
|
*
|
||||||
GraphQLInterfaceType |
|
* @package GraphQL\Type\Definition
|
||||||
GraphQLUnionType |
|
*/
|
||||||
GraphQLEnumType |
|
|
||||||
GraphQLInputObjectType |
|
|
||||||
GraphQLList |
|
|
||||||
GraphQLNonNull;
|
|
||||||
*/
|
|
||||||
abstract class Type implements \JsonSerializable
|
abstract class Type implements \JsonSerializable
|
||||||
{
|
{
|
||||||
const STRING = 'String';
|
const STRING = 'String';
|
||||||
@ -29,6 +24,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
private static $internalTypes;
|
private static $internalTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return IDType
|
* @return IDType
|
||||||
*/
|
*/
|
||||||
public static function id()
|
public static function id()
|
||||||
@ -37,6 +33,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return StringType
|
* @return StringType
|
||||||
*/
|
*/
|
||||||
public static function string()
|
public static function string()
|
||||||
@ -45,6 +42,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return BooleanType
|
* @return BooleanType
|
||||||
*/
|
*/
|
||||||
public static function boolean()
|
public static function boolean()
|
||||||
@ -53,6 +51,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return IntType
|
* @return IntType
|
||||||
*/
|
*/
|
||||||
public static function int()
|
public static function int()
|
||||||
@ -61,6 +60,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return FloatType
|
* @return FloatType
|
||||||
*/
|
*/
|
||||||
public static function float()
|
public static function float()
|
||||||
@ -69,7 +69,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $wrappedType
|
* @api
|
||||||
|
* @param ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType $wrappedType
|
||||||
* @return ListOfType
|
* @return ListOfType
|
||||||
*/
|
*/
|
||||||
public static function listOf($wrappedType)
|
public static function listOf($wrappedType)
|
||||||
@ -78,7 +79,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $wrappedType
|
* @api
|
||||||
|
* @param ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType $wrappedType
|
||||||
* @return NonNull
|
* @return NonNull
|
||||||
*/
|
*/
|
||||||
public static function nonNull($wrappedType)
|
public static function nonNull($wrappedType)
|
||||||
@ -113,7 +115,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
|
* @param Type $type
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isInputType($type)
|
public static function isInputType($type)
|
||||||
@ -123,7 +126,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
|
* @param Type $type
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isOutputType($type)
|
public static function isOutputType($type)
|
||||||
@ -133,6 +137,7 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @param $type
|
* @param $type
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
@ -142,7 +147,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
|
* @param Type $type
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isCompositeType($type)
|
public static function isCompositeType($type)
|
||||||
@ -151,7 +157,8 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
|
* @param Type $type
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public static function isAbstractType($type)
|
public static function isAbstractType($type)
|
||||||
@ -160,8 +167,9 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
* @return Type
|
* @param Type $type
|
||||||
|
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType|ListOfType
|
||||||
*/
|
*/
|
||||||
public static function getNullableType($type)
|
public static function getNullableType($type)
|
||||||
{
|
{
|
||||||
@ -169,8 +177,9 @@ abstract class Type implements \JsonSerializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @api
|
||||||
* @return UnmodifiedType
|
* @param Type $type
|
||||||
|
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
*/
|
*/
|
||||||
public static function getNamedType($type)
|
public static function getNamedType($type)
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace GraphQL\Type\Definition;
|
namespace GraphQL\Type\Definition;
|
||||||
|
|
||||||
/*
|
|
||||||
NonNullType
|
|
||||||
ListOfType
|
|
||||||
*/
|
|
||||||
interface WrappingType
|
interface WrappingType
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param bool $recurse
|
* @param bool $recurse
|
||||||
* @return Type
|
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||||
*/
|
*/
|
||||||
public function getWrappedType($recurse = false);
|
public function getWrappedType($recurse = false);
|
||||||
}
|
}
|
||||||
|
@ -16,29 +16,24 @@ use GraphQL\Utils\TypeInfo;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schema Definition
|
* Schema Definition (see [related docs](type-system/schema/))
|
||||||
*
|
*
|
||||||
* A Schema is created by supplying the root types of each type of operation:
|
* A Schema is created by supplying the root types of each type of operation:
|
||||||
* query, mutation (optional) and subscription (optional). A schema definition is
|
* query, mutation (optional) and subscription (optional). A schema definition is
|
||||||
* then supplied to the validator and executor.
|
* then supplied to the validator and executor. Usage Example:
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
*
|
*
|
||||||
* $schema = new GraphQL\Type\Schema([
|
* $schema = new GraphQL\Type\Schema([
|
||||||
* 'query' => $MyAppQueryRootType,
|
* 'query' => $MyAppQueryRootType,
|
||||||
* 'mutation' => $MyAppMutationRootType,
|
* 'mutation' => $MyAppMutationRootType,
|
||||||
* ]);
|
* ]);
|
||||||
*
|
*
|
||||||
* Note: If an array of `directives` are provided to GraphQL\Schema, that will be
|
* Or using Schema Config instance:
|
||||||
* the exact list of directives represented and allowed. If `directives` is not
|
|
||||||
* provided then a default set of the specified directives (e.g. @include and
|
|
||||||
* @skip) will be used. If you wish to provide *additional* directives to these
|
|
||||||
* specified directives, you must explicitly declare them. Example:
|
|
||||||
*
|
*
|
||||||
* $mySchema = new GraphQL\Schema([
|
* $config = GraphQL\Type\SchemaConfig::create()
|
||||||
* ...
|
* ->setQuery($MyAppQueryRootType)
|
||||||
* 'directives' => array_merge(GraphQL::getInternalDirectives(), [ $myCustomDirective ]),
|
* ->setMutation($MyAppMutationRootType);
|
||||||
* ])
|
*
|
||||||
|
* $schema = new GraphQL\Type\Schema($config);
|
||||||
*
|
*
|
||||||
* @package GraphQL
|
* @package GraphQL
|
||||||
*/
|
*/
|
||||||
@ -71,9 +66,10 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Schema constructor.
|
* Schema constructor.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param array|SchemaConfig $config
|
* @param array|SchemaConfig $config
|
||||||
*/
|
*/
|
||||||
public function __construct($config = null)
|
public function __construct($config)
|
||||||
{
|
{
|
||||||
if (func_num_args() > 1 || $config instanceof Type) {
|
if (func_num_args() > 1 || $config instanceof Type) {
|
||||||
trigger_error(
|
trigger_error(
|
||||||
@ -131,6 +127,7 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Returns schema query type
|
* Returns schema query type
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return ObjectType
|
* @return ObjectType
|
||||||
*/
|
*/
|
||||||
public function getQueryType()
|
public function getQueryType()
|
||||||
@ -141,6 +138,7 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Returns schema mutation type
|
* Returns schema mutation type
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return ObjectType|null
|
* @return ObjectType|null
|
||||||
*/
|
*/
|
||||||
public function getMutationType()
|
public function getMutationType()
|
||||||
@ -151,6 +149,7 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Returns schema subscription
|
* Returns schema subscription
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return ObjectType|null
|
* @return ObjectType|null
|
||||||
*/
|
*/
|
||||||
public function getSubscriptionType()
|
public function getSubscriptionType()
|
||||||
@ -159,6 +158,7 @@ class Schema
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @api
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
public function getConfig()
|
public function getConfig()
|
||||||
@ -172,6 +172,7 @@ class Schema
|
|||||||
*
|
*
|
||||||
* This operation requires full schema scan. Do not use in production environment.
|
* This operation requires full schema scan. Do not use in production environment.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return Type[]
|
* @return Type[]
|
||||||
*/
|
*/
|
||||||
public function getTypeMap()
|
public function getTypeMap()
|
||||||
@ -186,6 +187,7 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Returns type by it's name
|
* Returns type by it's name
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return Type
|
* @return Type
|
||||||
*/
|
*/
|
||||||
@ -248,6 +250,7 @@ class Schema
|
|||||||
*
|
*
|
||||||
* This operation requires full schema scan. Do not use in production environment.
|
* This operation requires full schema scan. Do not use in production environment.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param AbstractType $abstractType
|
* @param AbstractType $abstractType
|
||||||
* @return ObjectType[]
|
* @return ObjectType[]
|
||||||
*/
|
*/
|
||||||
@ -311,6 +314,7 @@ class Schema
|
|||||||
* Returns true if object type is concrete type of given abstract type
|
* Returns true if object type is concrete type of given abstract type
|
||||||
* (implementation for interfaces and members of union type for unions)
|
* (implementation for interfaces and members of union type for unions)
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param AbstractType $abstractType
|
* @param AbstractType $abstractType
|
||||||
* @param ObjectType $possibleType
|
* @param ObjectType $possibleType
|
||||||
* @return bool
|
* @return bool
|
||||||
@ -328,16 +332,18 @@ class Schema
|
|||||||
/**
|
/**
|
||||||
* Returns a list of directives supported by this schema
|
* Returns a list of directives supported by this schema
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @return Directive[]
|
* @return Directive[]
|
||||||
*/
|
*/
|
||||||
public function getDirectives()
|
public function getDirectives()
|
||||||
{
|
{
|
||||||
return $this->config->directives ?: GraphQL::getInternalDirectives();
|
return $this->config->directives ?: GraphQL::getStandardDirectives();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns instance of directive by name
|
* Returns instance of directive by name
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param $name
|
* @param $name
|
||||||
* @return Directive
|
* @return Directive
|
||||||
*/
|
*/
|
||||||
@ -367,6 +373,7 @@ class Schema
|
|||||||
*
|
*
|
||||||
* This operation requires full schema scan. Do not use in production environment.
|
* This operation requires full schema scan. Do not use in production environment.
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @throws InvariantViolation
|
* @throws InvariantViolation
|
||||||
*/
|
*/
|
||||||
public function assertValid()
|
public function assertValid()
|
||||||
|
@ -7,10 +7,18 @@ use GraphQL\Type\Definition\Type;
|
|||||||
use GraphQL\Utils\Utils;
|
use GraphQL\Utils\Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Config
|
* Schema configuration class.
|
||||||
* Note: properties are marked as public for performance reasons. They should be considered read-only.
|
* Could be passed directly to schema constructor. List of options accepted by **create** method is
|
||||||
|
* [described in docs](type-system/schema/#configuration-options).
|
||||||
|
*
|
||||||
|
* Usage example:
|
||||||
|
*
|
||||||
|
* $config = SchemaConfig::create()
|
||||||
|
* ->setQuery($myQueryType)
|
||||||
|
* ->setTypeLoader($myTypeLoader);
|
||||||
|
*
|
||||||
|
* $schema = new Schema($config);
|
||||||
*
|
*
|
||||||
* @package GraphQL
|
|
||||||
*/
|
*/
|
||||||
class SchemaConfig
|
class SchemaConfig
|
||||||
{
|
{
|
||||||
@ -46,7 +54,9 @@ class SchemaConfig
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an array of options to instance of SchemaConfig
|
* Converts an array of options to instance of SchemaConfig
|
||||||
|
* (or just returns empty config when array is not passed).
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param array $options
|
* @param array $options
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -128,14 +138,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ObjectType
|
* @api
|
||||||
*/
|
|
||||||
public function getQuery()
|
|
||||||
{
|
|
||||||
return $this->query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ObjectType $query
|
* @param ObjectType $query
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -146,14 +149,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ObjectType
|
* @api
|
||||||
*/
|
|
||||||
public function getMutation()
|
|
||||||
{
|
|
||||||
return $this->mutation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ObjectType $mutation
|
* @param ObjectType $mutation
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -164,14 +160,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ObjectType
|
* @api
|
||||||
*/
|
|
||||||
public function getSubscription()
|
|
||||||
{
|
|
||||||
return $this->subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param ObjectType $subscription
|
* @param ObjectType $subscription
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -182,14 +171,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Type[]
|
* @api
|
||||||
*/
|
|
||||||
public function getTypes()
|
|
||||||
{
|
|
||||||
return $this->types ?: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Type[]|callable $types
|
* @param Type[]|callable $types
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -200,14 +182,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Directive[]
|
* @api
|
||||||
*/
|
|
||||||
public function getDirectives()
|
|
||||||
{
|
|
||||||
return $this->directives ?: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Directive[] $directives
|
* @param Directive[] $directives
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -218,14 +193,7 @@ class SchemaConfig
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return callable
|
* @api
|
||||||
*/
|
|
||||||
public function getTypeLoader()
|
|
||||||
{
|
|
||||||
return $this->typeLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param callable $typeLoader
|
* @param callable $typeLoader
|
||||||
* @return SchemaConfig
|
* @return SchemaConfig
|
||||||
*/
|
*/
|
||||||
@ -234,4 +202,58 @@ class SchemaConfig
|
|||||||
$this->typeLoader = $typeLoader;
|
$this->typeLoader = $typeLoader;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return ObjectType
|
||||||
|
*/
|
||||||
|
public function getQuery()
|
||||||
|
{
|
||||||
|
return $this->query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return ObjectType
|
||||||
|
*/
|
||||||
|
public function getMutation()
|
||||||
|
{
|
||||||
|
return $this->mutation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return ObjectType
|
||||||
|
*/
|
||||||
|
public function getSubscription()
|
||||||
|
{
|
||||||
|
return $this->subscription;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return Type[]
|
||||||
|
*/
|
||||||
|
public function getTypes()
|
||||||
|
{
|
||||||
|
return $this->types ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return Directive[]
|
||||||
|
*/
|
||||||
|
public function getDirectives()
|
||||||
|
{
|
||||||
|
return $this->directives ?: [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api
|
||||||
|
* @return callable
|
||||||
|
*/
|
||||||
|
public function getTypeLoader()
|
||||||
|
{
|
||||||
|
return $this->typeLoader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class TypeInfo
|
|||||||
Warning::warnOnce(
|
Warning::warnOnce(
|
||||||
'One of the schema types is not a valid type definition instance. '.
|
'One of the schema types is not a valid type definition instance. '.
|
||||||
'Try running $schema->assertValid() to find out the cause of this warning.',
|
'Try running $schema->assertValid() to find out the cause of this warning.',
|
||||||
Warning::NOT_A_TYPE
|
Warning::WARNING_NOT_A_TYPE
|
||||||
);
|
);
|
||||||
return $typeMap;
|
return $typeMap;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class Utils
|
|||||||
$cls = get_class($obj);
|
$cls = get_class($obj);
|
||||||
Warning::warn(
|
Warning::warn(
|
||||||
"Trying to set non-existing property '$key' on class '$cls'",
|
"Trying to set non-existing property '$key' on class '$cls'",
|
||||||
Warning::ASSIGN_WARNING
|
Warning::WARNING_ASSIGN
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$obj->{$key} = $value;
|
$obj->{$key} = $value;
|
||||||
@ -437,7 +437,7 @@ class Utils
|
|||||||
'Name "'.$name.'" must not begin with "__", which is reserved by ' .
|
'Name "'.$name.'" must not begin with "__", which is reserved by ' .
|
||||||
'GraphQL introspection. In a future release of graphql this will ' .
|
'GraphQL introspection. In a future release of graphql this will ' .
|
||||||
'become an exception',
|
'become an exception',
|
||||||
Warning::NAME_WARNING
|
Warning::WARNING_NAME
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,24 @@ use GraphQL\Validator\Rules\UniqueVariableNames;
|
|||||||
use GraphQL\Validator\Rules\VariablesAreInputTypes;
|
use GraphQL\Validator\Rules\VariablesAreInputTypes;
|
||||||
use GraphQL\Validator\Rules\VariablesInAllowedPosition;
|
use GraphQL\Validator\Rules\VariablesInAllowedPosition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the "Validation" section of the spec.
|
||||||
|
*
|
||||||
|
* Validation runs synchronously, returning an array of encountered errors, or
|
||||||
|
* an empty array if no errors were encountered and the document is valid.
|
||||||
|
*
|
||||||
|
* A list of specific validation rules may be provided. If not provided, the
|
||||||
|
* default list of rules defined by the GraphQL specification will be used.
|
||||||
|
*
|
||||||
|
* Each validation rule is an instance of GraphQL\Validator\Rules\AbstractValidationRule
|
||||||
|
* which returns a visitor (see the [GraphQL\Language\Visitor API](reference/#graphqllanguagevisitor)).
|
||||||
|
*
|
||||||
|
* Visitor methods are expected to return an instance of [GraphQL\Error\Error](reference/#graphqlerrorerror),
|
||||||
|
* or array of such instances when invalid.
|
||||||
|
*
|
||||||
|
* Optionally a custom TypeInfo instance may be provided. If not provided, one
|
||||||
|
* will be created from the provided schema.
|
||||||
|
*/
|
||||||
class DocumentValidator
|
class DocumentValidator
|
||||||
{
|
{
|
||||||
private static $rules = [];
|
private static $rules = [];
|
||||||
@ -59,9 +77,36 @@ class DocumentValidator
|
|||||||
private static $initRules = false;
|
private static $initRules = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all validation rules
|
* Primary method for query validation. See class description for details.
|
||||||
*
|
*
|
||||||
* @return callable[]
|
* @api
|
||||||
|
* @param Schema $schema
|
||||||
|
* @param DocumentNode $ast
|
||||||
|
* @param AbstractValidationRule[]|null $rules
|
||||||
|
* @param TypeInfo|null $typeInfo
|
||||||
|
* @return Error[]
|
||||||
|
*/
|
||||||
|
public static function validate(
|
||||||
|
Schema $schema,
|
||||||
|
DocumentNode $ast,
|
||||||
|
array $rules = null,
|
||||||
|
TypeInfo $typeInfo = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (null === $rules) {
|
||||||
|
$rules = static::allRules();
|
||||||
|
}
|
||||||
|
$typeInfo = $typeInfo ?: new TypeInfo($schema);
|
||||||
|
$errors = static::visitUsingRules($schema, $typeInfo, $ast, $rules);
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all global validation rules.
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
* @return AbstractValidationRule[]
|
||||||
*/
|
*/
|
||||||
public static function allRules()
|
public static function allRules()
|
||||||
{
|
{
|
||||||
@ -128,8 +173,12 @@ class DocumentValidator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns validation rule
|
* Returns global validation rule by name. Standard rules are named by class name, so
|
||||||
|
* example usage for such rules:
|
||||||
*
|
*
|
||||||
|
* $rule = DocumentValidator::getRule(GraphQL\Validator\Rules\QueryComplexity::class);
|
||||||
|
*
|
||||||
|
* @api
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @return AbstractValidationRule
|
* @return AbstractValidationRule
|
||||||
*/
|
*/
|
||||||
@ -146,8 +195,9 @@ class DocumentValidator
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add rule to list of default validation rules
|
* Add rule to list of global validation rules
|
||||||
*
|
*
|
||||||
|
* @api
|
||||||
* @param AbstractValidationRule $rule
|
* @param AbstractValidationRule $rule
|
||||||
*/
|
*/
|
||||||
public static function addRule(AbstractValidationRule $rule)
|
public static function addRule(AbstractValidationRule $rule)
|
||||||
@ -155,43 +205,6 @@ class DocumentValidator
|
|||||||
self::$rules[$rule->getName()] = $rule;
|
self::$rules[$rule->getName()] = $rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the "Validation" section of the spec.
|
|
||||||
*
|
|
||||||
* Validation runs synchronously, returning an array of encountered errors, or
|
|
||||||
* an empty array if no errors were encountered and the document is valid.
|
|
||||||
*
|
|
||||||
* A list of specific validation rules may be provided. If not provided, the
|
|
||||||
* default list of rules defined by the GraphQL specification will be used.
|
|
||||||
*
|
|
||||||
* Each validation rules is a function which returns a visitor
|
|
||||||
* (see the GraphQL\Language\Visitor API). Visitor methods are expected to return
|
|
||||||
* GraphQL\Error\Error, or arrays of GraphQL\Error\Error when invalid.
|
|
||||||
*
|
|
||||||
* Optionally a custom TypeInfo instance may be provided. If not provided, one
|
|
||||||
* will be created from the provided schema.
|
|
||||||
*
|
|
||||||
* @param Schema $schema
|
|
||||||
* @param DocumentNode $ast
|
|
||||||
* @param array|null $rules
|
|
||||||
* @param TypeInfo|null $typeInfo
|
|
||||||
* @return Error[]
|
|
||||||
*/
|
|
||||||
public static function validate(
|
|
||||||
Schema $schema,
|
|
||||||
DocumentNode $ast,
|
|
||||||
array $rules = null,
|
|
||||||
TypeInfo $typeInfo = null
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (null === $rules) {
|
|
||||||
$rules = static::allRules();
|
|
||||||
}
|
|
||||||
$typeInfo = $typeInfo ?: new TypeInfo($schema);
|
|
||||||
$errors = static::visitUsingRules($schema, $typeInfo, $ast, $rules);
|
|
||||||
return $errors;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function isError($value)
|
public static function isError($value)
|
||||||
{
|
{
|
||||||
return is_array($value)
|
return is_array($value)
|
||||||
|
@ -87,9 +87,9 @@ class AbstractPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$result = GraphQL::execute($schema, $query);
|
$result = GraphQL::execute($schema, $query);
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'data' => [
|
'data' => [
|
||||||
@ -174,9 +174,9 @@ class AbstractPromiseTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
}';
|
}';
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$result = GraphQL::execute($schema, $query);
|
$result = GraphQL::execute($schema, $query);
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
|
|
||||||
$expected = [
|
$expected = [
|
||||||
'data' => [
|
'data' => [
|
||||||
|
@ -122,11 +122,11 @@ class ExecutorLazySchemaTest extends \PHPUnit_Framework_TestCase
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$result = Executor::execute($schema, Parser::parse($query));
|
$result = Executor::execute($schema, Parser::parse($query));
|
||||||
$this->assertEquals($expected, $result);
|
$this->assertEquals($expected, $result);
|
||||||
|
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$result = Executor::execute($schema, Parser::parse($query));
|
$result = Executor::execute($schema, Parser::parse($query));
|
||||||
$this->assertEquals(1, count($result->errors));
|
$this->assertEquals(1, count($result->errors));
|
||||||
$this->assertInstanceOf('PHPUnit_Framework_Error_Warning', $result->errors[0]->getPrevious());
|
$this->assertInstanceOf('PHPUnit_Framework_Error_Warning', $result->errors[0]->getPrevious());
|
||||||
|
@ -256,9 +256,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -294,9 +294,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,9 +351,9 @@ class UnionInterfaceTest extends \PHPUnit_Framework_TestCase
|
|||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
Warning::suppress(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::suppress(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
$this->assertEquals($expected, Executor::execute($this->schema, $ast, $this->john)->toArray());
|
||||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,7 +175,7 @@ class RequestParsingTest extends \PHPUnit_Framework_TestCase
|
|||||||
} catch (InvariantViolation $e) {
|
} catch (InvariantViolation $e) {
|
||||||
// Expecting parsing exception to be thrown somewhere else:
|
// Expecting parsing exception to be thrown somewhere else:
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
'PSR request is expected to provide parsed body for "application/json" requests but got null',
|
'PSR-7 request is expected to provide parsed body for "application/json" requests but got null',
|
||||||
$e->getMessage()
|
$e->getMessage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -15,13 +15,13 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
Warning::suppress(Warning::CONFIG_DEPRECATION_WARNING);
|
Warning::suppress(Warning::WARNING_CONFIG_DEPRECATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function tearDownAfterClass()
|
public static function tearDownAfterClass()
|
||||||
{
|
{
|
||||||
Config::disableValidation();
|
Config::disableValidation();
|
||||||
Warning::enable(Warning::CONFIG_DEPRECATION_WARNING);
|
Warning::enable(Warning::WARNING_CONFIG_DEPRECATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testToggling()
|
public function testToggling()
|
||||||
|
@ -122,13 +122,13 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
$this->notInputTypes[] = $this->String;
|
$this->notInputTypes[] = $this->String;
|
||||||
|
|
||||||
Warning::suppress(Warning::NOT_A_TYPE);
|
Warning::suppress(Warning::WARNING_NOT_A_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown()
|
public function tearDown()
|
||||||
{
|
{
|
||||||
parent::tearDown();
|
parent::tearDown();
|
||||||
Warning::enable(Warning::NOT_A_TYPE);
|
Warning::enable(Warning::WARNING_NOT_A_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRejectsTypesWithoutNames()
|
public function testRejectsTypesWithoutNames()
|
||||||
|
Loading…
Reference in New Issue
Block a user