mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-29 00:25:17 +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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @api
|
||||
* @return string
|
||||
*/
|
||||
public function getCategory();
|
||||
|
@ -1,7 +1,9 @@
|
||||
<?php
|
||||
namespace GraphQL\Error;
|
||||
|
||||
|
||||
/**
|
||||
* Collection of flags for [error debugging](error-handling/#debugging-tools).
|
||||
*/
|
||||
class Debug
|
||||
{
|
||||
const INCLUDE_DEBUG_MESSAGE = 1;
|
||||
|
@ -6,13 +6,18 @@ use GraphQL\Language\SourceLocation;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Class Error
|
||||
* A GraphQLError describes an Error found during the parse, validate, or
|
||||
* Describes an Error found during the parse, validate, or
|
||||
* execute phases of performing a GraphQL operation. In addition to a message
|
||||
* and stack trace, it also includes information about the locations in a
|
||||
* GraphQL document and/or execution result that correspond to the Error.
|
||||
*
|
||||
* @package GraphQL
|
||||
* 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
|
||||
{
|
||||
@ -27,13 +32,6 @@ class Error extends \Exception implements \JsonSerializable, ClientAware
|
||||
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[]
|
||||
*/
|
||||
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[]
|
||||
*/
|
||||
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
|
||||
* corresponds to this error. Only included for errors during execution.
|
||||
* Returns an array describing the path from the root value to the field which produced this error.
|
||||
* Only included for execution errors.
|
||||
*
|
||||
* @api
|
||||
* @return array|null
|
||||
*/
|
||||
public function getPath()
|
||||
|
@ -7,23 +7,36 @@ use GraphQL\Type\Definition\WrappingType;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Class FormattedError
|
||||
*
|
||||
* @package GraphQL\Error
|
||||
* 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)
|
||||
* and provides tools for error debugging.
|
||||
*/
|
||||
class FormattedError
|
||||
{
|
||||
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)
|
||||
{
|
||||
self::$internalErrorMessage = $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard GraphQL error formatter. Converts any exception to GraphQL error
|
||||
* conforming to GraphQL spec
|
||||
* Standard GraphQL error formatter. Converts any exception to array
|
||||
* 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 bool|int $debug
|
||||
* @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 \Throwable $e
|
||||
* @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
|
||||
* @return array
|
||||
*/
|
||||
|
@ -1,15 +1,20 @@
|
||||
<?php
|
||||
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
|
||||
{
|
||||
const NAME_WARNING = 1;
|
||||
const ASSIGN_WARNING = 2;
|
||||
const CONFIG_WARNING = 4;
|
||||
const FULL_SCHEMA_SCAN_WARNING = 8;
|
||||
const CONFIG_DEPRECATION_WARNING = 16;
|
||||
const NOT_A_TYPE = 32;
|
||||
|
||||
const WARNING_NAME = 1;
|
||||
const WARNING_ASSIGN = 2;
|
||||
const WARNING_CONFIG = 4;
|
||||
const WARNING_FULL_SCHEMA_SCAN = 8;
|
||||
const WARNING_CONFIG_DEPRECATION = 16;
|
||||
const WARNING_NOT_A_TYPE = 32;
|
||||
const ALL = 63;
|
||||
|
||||
static $enableWarnings = self::ALL;
|
||||
@ -19,9 +24,10 @@ final class Warning
|
||||
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.
|
||||
*
|
||||
* @api
|
||||
* @param callable|null $warningHandler
|
||||
*/
|
||||
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)
|
||||
*
|
||||
* Usage example:
|
||||
* Warning::suppress(Warning::NOT_A_TYPE)
|
||||
* Warning::suppress(Warning::WARNING_NOT_A_TYPE)
|
||||
*
|
||||
* When passing true - suppresses all warnings.
|
||||
*
|
||||
* @api
|
||||
* @param bool|int $suppress
|
||||
*/
|
||||
static function suppress($suppress = true)
|
||||
@ -55,10 +62,11 @@ final class Warning
|
||||
* Re-enable previously suppressed warning by id
|
||||
*
|
||||
* Usage example:
|
||||
* Warning::suppress(Warning::NOT_A_TYPE)
|
||||
* Warning::suppress(Warning::WARNING_NOT_A_TYPE)
|
||||
*
|
||||
* When passing true - re-enables all warnings.
|
||||
*
|
||||
* @api
|
||||
* @param bool|int $enable
|
||||
*/
|
||||
public static function enable($enable = true)
|
||||
|
@ -11,6 +11,8 @@ use GraphQL\Type\Schema;
|
||||
*
|
||||
* Namely, schema of the type system that is currently executing,
|
||||
* and the fragments defined in the query document
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ExecutionContext
|
||||
{
|
||||
|
@ -4,19 +4,40 @@ namespace GraphQL\Executor;
|
||||
use GraphQL\Error\Error;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Data collected from resolvers during query execution
|
||||
*
|
||||
* @api
|
||||
* @var array
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
* User-defined serializable array of extensions included in serialized result.
|
||||
* Conforms to
|
||||
*
|
||||
* @api
|
||||
* @var array
|
||||
*/
|
||||
public $extensions;
|
||||
@ -56,6 +77,7 @@ class ExecutionResult implements \JsonSerializable
|
||||
* // ... other keys
|
||||
* );
|
||||
*
|
||||
* @api
|
||||
* @param callable $errorFormatter
|
||||
* @return $this
|
||||
*/
|
||||
@ -75,6 +97,7 @@ class ExecutionResult implements \JsonSerializable
|
||||
* return array_map($formatter, $errors);
|
||||
* }
|
||||
*
|
||||
* @api
|
||||
* @param callable $handler
|
||||
* @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
|
||||
* Default error handler will simply return all errors formatted. No errors are filtered.
|
||||
* If debug argument is passed, output of error formatter is enriched which debugging information
|
||||
* ("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
|
||||
* @return array
|
||||
*/
|
||||
|
@ -31,23 +31,7 @@ use GraphQL\Utils\TypeInfo;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Terminology
|
||||
*
|
||||
* "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 }"
|
||||
* Implements the "Evaluating requests" section of the GraphQL specification.
|
||||
*/
|
||||
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 DocumentNode $ast
|
||||
* @param $rootValue
|
||||
@ -134,9 +122,12 @@ class Executor
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes DocumentNode against given $schema using given $promiseAdapter for deferred resolvers.
|
||||
* Returns promise which is always fullfilled with instance of ExecutionResult
|
||||
* Same as executeQuery(), but requires promise adapter and returns a promise which is always
|
||||
* fulfilled with an instance of ExecutionResult and never rejected.
|
||||
*
|
||||
* Useful for async PHP platforms.
|
||||
*
|
||||
* @api
|
||||
* @param PromiseAdapter $promiseAdapter
|
||||
* @param Schema $schema
|
||||
* @param DocumentNode $ast
|
||||
@ -1083,7 +1074,7 @@ class Executor
|
||||
'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. '.
|
||||
' 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);
|
||||
|
@ -1,19 +1,24 @@
|
||||
<?php
|
||||
namespace GraphQL\Executor\Promise;
|
||||
|
||||
/**
|
||||
* Provides a means for integration of async PHP platforms ([related docs](data-fetching/#async-php))
|
||||
*/
|
||||
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
|
||||
* @return bool
|
||||
*/
|
||||
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
|
||||
* @return Promise
|
||||
*/
|
||||
@ -21,8 +26,9 @@ interface PromiseAdapter
|
||||
|
||||
/**
|
||||
* 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 callable|null $onFulfilled
|
||||
* @param callable|null $onRejected
|
||||
@ -34,8 +40,11 @@ interface PromiseAdapter
|
||||
/**
|
||||
* Creates a Promise
|
||||
*
|
||||
* Expected resolver signature:
|
||||
* function(callable $resolve, callable $reject)
|
||||
*
|
||||
* @api
|
||||
* @param callable $resolver
|
||||
|
||||
* @return Promise
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @api
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Promise
|
||||
*/
|
||||
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
|
||||
* the provided reason is a promise, then it is returned as-is.
|
||||
*
|
||||
* @api
|
||||
* @param \Throwable $reason
|
||||
*
|
||||
* @return Promise
|
||||
*/
|
||||
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
|
||||
* items in the array are fulfilled.
|
||||
*
|
||||
* @api
|
||||
* @param array $promisesOrValues Promises or values.
|
||||
*
|
||||
* @return Promise
|
||||
*/
|
||||
public function all(array $promisesOrValues);
|
||||
|
@ -13,26 +13,34 @@ use GraphQL\Executor\Promise\PromiseAdapter;
|
||||
use GraphQL\Type\Definition\Directive;
|
||||
use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Validator\DocumentValidator;
|
||||
use GraphQL\Validator\Rules\AbstractValidationRule;
|
||||
use GraphQL\Validator\Rules\QueryComplexity;
|
||||
|
||||
/**
|
||||
* This is the primary facade for fulfilling GraphQL operations.
|
||||
* See [related documentation](executing-queries/).
|
||||
*/
|
||||
class GraphQL
|
||||
{
|
||||
/**
|
||||
* This is the primary entry point function for fulfilling GraphQL operations
|
||||
* by parsing, validating, and executing a GraphQL document along side a
|
||||
* GraphQL schema.
|
||||
* Executes graphql query.
|
||||
*
|
||||
* More sophisticated GraphQL servers, such as those which persist queries,
|
||||
* may wish to separate the validation and execution phases to a static time
|
||||
* tooling step, and a server runtime step.
|
||||
*
|
||||
* Available options:
|
||||
*
|
||||
* schema:
|
||||
* The GraphQL type system to use when validating and executing a query.
|
||||
* requestString:
|
||||
* source:
|
||||
* A GraphQL language formatted string representing the requested operation.
|
||||
* rootValue:
|
||||
* The value provided as the first argument to resolver functions on the top
|
||||
* 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:
|
||||
* A mapping of variable name to runtime value to use for all variables
|
||||
* defined in the requestString.
|
||||
@ -49,6 +57,7 @@ class GraphQL
|
||||
* Empty array would allow to skip query validation (may be convenient for persisted
|
||||
* queries which are validated before persisting and assumed valid during execution)
|
||||
*
|
||||
* @api
|
||||
* @param \GraphQL\Type\Schema $schema
|
||||
* @param string|DocumentNode $source
|
||||
* @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 \GraphQL\Type\Schema $schema
|
||||
* @param string|DocumentNode $source
|
||||
@ -230,6 +241,7 @@ class GraphQL
|
||||
/**
|
||||
* Returns directives defined in GraphQL spec
|
||||
*
|
||||
* @api
|
||||
* @return Directive[]
|
||||
*/
|
||||
public static function getStandardDirectives()
|
||||
@ -240,6 +252,7 @@ class GraphQL
|
||||
/**
|
||||
* Returns types defined in GraphQL spec
|
||||
*
|
||||
* @api
|
||||
* @return Type[]
|
||||
*/
|
||||
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()
|
||||
{
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace GraphQL\Language;
|
||||
|
||||
// language/parser.js
|
||||
|
||||
use GraphQL\Language\AST\ArgumentNode;
|
||||
use GraphQL\Language\AST\DirectiveDefinitionNode;
|
||||
use GraphQL\Language\AST\EnumTypeDefinitionNode;
|
||||
@ -45,9 +43,15 @@ use GraphQL\Language\AST\VariableNode;
|
||||
use GraphQL\Language\AST\VariableDefinitionNode;
|
||||
use GraphQL\Error\SyntaxError;
|
||||
|
||||
/**
|
||||
* Parses string containing GraphQL query or [type definition](type-system/type-language/) to Abstract Syntax Tree.
|
||||
*/
|
||||
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:
|
||||
*
|
||||
* noLocation: boolean,
|
||||
@ -55,6 +59,7 @@ class Parser
|
||||
* in the source that they correspond to. This configuration flag
|
||||
* disables that behavior for performance or testing.)
|
||||
*
|
||||
* @api
|
||||
* @param Source|string $source
|
||||
* @param array $options
|
||||
* @return DocumentNode
|
||||
@ -66,17 +71,17 @@ class Parser
|
||||
return $parser->parseDocument();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
|
||||
* 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
|
||||
* 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 array $options
|
||||
* @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
|
||||
* 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
|
||||
* 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 array $options
|
||||
* @return ListTypeNode|NameNode|NonNullTypeNode
|
||||
|
@ -40,11 +40,24 @@ use GraphQL\Language\AST\UnionTypeDefinitionNode;
|
||||
use GraphQL\Language\AST\VariableDefinitionNode;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Prints AST to string. Capable of printing GraphQL queries and Type definition language.
|
||||
*
|
||||
* @api
|
||||
* @param Node $ast
|
||||
* @return string
|
||||
*/
|
||||
|
@ -15,88 +15,10 @@ class VisitorOperation
|
||||
public $removeNode;
|
||||
}
|
||||
|
||||
class Visitor
|
||||
{
|
||||
/**
|
||||
* Returns marker for visitor break
|
||||
* Utility for efficient AST traversal and modification.
|
||||
*
|
||||
* @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 = [
|
||||
NodeKind::NAME => [],
|
||||
NodeKind::DOCUMENT => ['definitions'],
|
||||
NodeKind::OPERATION_DEFINITION => ['name', 'variableDefinitions', 'directives', 'selectionSet'],
|
||||
NodeKind::VARIABLE_DEFINITION => ['variable', 'type', 'defaultValue'],
|
||||
NodeKind::VARIABLE => ['name'],
|
||||
NodeKind::SELECTION_SET => ['selections'],
|
||||
NodeKind::FIELD => ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
|
||||
NodeKind::ARGUMENT => ['name', 'value'],
|
||||
NodeKind::FRAGMENT_SPREAD => ['name', 'directives'],
|
||||
NodeKind::INLINE_FRAGMENT => ['typeCondition', 'directives', 'selectionSet'],
|
||||
NodeKind::FRAGMENT_DEFINITION => ['name', 'typeCondition', 'directives', 'selectionSet'],
|
||||
|
||||
NodeKind::INT => [],
|
||||
NodeKind::FLOAT => [],
|
||||
NodeKind::STRING => [],
|
||||
NodeKind::BOOLEAN => [],
|
||||
NodeKind::NULL => [],
|
||||
NodeKind::ENUM => [],
|
||||
NodeKind::LST => ['values'],
|
||||
NodeKind::OBJECT => ['fields'],
|
||||
NodeKind::OBJECT_FIELD => ['name', 'value'],
|
||||
NodeKind::DIRECTIVE => ['name', 'arguments'],
|
||||
NodeKind::NAMED_TYPE => ['name'],
|
||||
NodeKind::LIST_TYPE => ['type'],
|
||||
NodeKind::NON_NULL_TYPE => ['type'],
|
||||
|
||||
NodeKind::SCHEMA_DEFINITION => ['directives', 'operationTypes'],
|
||||
NodeKind::OPERATION_TYPE_DEFINITION => ['type'],
|
||||
NodeKind::SCALAR_TYPE_DEFINITION => ['name', 'directives'],
|
||||
NodeKind::OBJECT_TYPE_DEFINITION => ['name', 'interfaces', 'directives', 'fields'],
|
||||
NodeKind::FIELD_DEFINITION => ['name', 'arguments', 'type', 'directives'],
|
||||
NodeKind::INPUT_VALUE_DEFINITION => ['name', 'type', 'defaultValue', 'directives'],
|
||||
NodeKind::INTERFACE_TYPE_DEFINITION => [ 'name', 'directives', 'fields' ],
|
||||
NodeKind::UNION_TYPE_DEFINITION => [ 'name', 'directives', 'types' ],
|
||||
NodeKind::ENUM_TYPE_DEFINITION => [ 'name', 'directives', 'values' ],
|
||||
NodeKind::ENUM_VALUE_DEFINITION => [ 'name', 'directives' ],
|
||||
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => [ 'name', 'directives', 'fields' ],
|
||||
NodeKind::TYPE_EXTENSION_DEFINITION => [ 'definition' ],
|
||||
NodeKind::DIRECTIVE_DEFINITION => [ 'name', 'arguments', 'locations' ]
|
||||
];
|
||||
|
||||
/**
|
||||
* visit() will walk through an AST using a depth first traversal, calling
|
||||
* `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.
|
||||
*
|
||||
@ -105,7 +27,7 @@ class Visitor
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
@ -128,8 +50,8 @@ class Visitor
|
||||
* ]);
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
@ -179,7 +101,55 @@ class Visitor
|
||||
* }
|
||||
* ]
|
||||
* ]);
|
||||
*/
|
||||
class Visitor
|
||||
{
|
||||
public static $visitorKeys = [
|
||||
NodeKind::NAME => [],
|
||||
NodeKind::DOCUMENT => ['definitions'],
|
||||
NodeKind::OPERATION_DEFINITION => ['name', 'variableDefinitions', 'directives', 'selectionSet'],
|
||||
NodeKind::VARIABLE_DEFINITION => ['variable', 'type', 'defaultValue'],
|
||||
NodeKind::VARIABLE => ['name'],
|
||||
NodeKind::SELECTION_SET => ['selections'],
|
||||
NodeKind::FIELD => ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
|
||||
NodeKind::ARGUMENT => ['name', 'value'],
|
||||
NodeKind::FRAGMENT_SPREAD => ['name', 'directives'],
|
||||
NodeKind::INLINE_FRAGMENT => ['typeCondition', 'directives', 'selectionSet'],
|
||||
NodeKind::FRAGMENT_DEFINITION => ['name', 'typeCondition', 'directives', 'selectionSet'],
|
||||
|
||||
NodeKind::INT => [],
|
||||
NodeKind::FLOAT => [],
|
||||
NodeKind::STRING => [],
|
||||
NodeKind::BOOLEAN => [],
|
||||
NodeKind::NULL => [],
|
||||
NodeKind::ENUM => [],
|
||||
NodeKind::LST => ['values'],
|
||||
NodeKind::OBJECT => ['fields'],
|
||||
NodeKind::OBJECT_FIELD => ['name', 'value'],
|
||||
NodeKind::DIRECTIVE => ['name', 'arguments'],
|
||||
NodeKind::NAMED_TYPE => ['name'],
|
||||
NodeKind::LIST_TYPE => ['type'],
|
||||
NodeKind::NON_NULL_TYPE => ['type'],
|
||||
|
||||
NodeKind::SCHEMA_DEFINITION => ['directives', 'operationTypes'],
|
||||
NodeKind::OPERATION_TYPE_DEFINITION => ['type'],
|
||||
NodeKind::SCALAR_TYPE_DEFINITION => ['name', 'directives'],
|
||||
NodeKind::OBJECT_TYPE_DEFINITION => ['name', 'interfaces', 'directives', 'fields'],
|
||||
NodeKind::FIELD_DEFINITION => ['name', 'arguments', 'type', 'directives'],
|
||||
NodeKind::INPUT_VALUE_DEFINITION => ['name', 'type', 'defaultValue', 'directives'],
|
||||
NodeKind::INTERFACE_TYPE_DEFINITION => [ 'name', 'directives', 'fields' ],
|
||||
NodeKind::UNION_TYPE_DEFINITION => [ 'name', 'directives', 'types' ],
|
||||
NodeKind::ENUM_TYPE_DEFINITION => [ 'name', 'directives', 'values' ],
|
||||
NodeKind::ENUM_VALUE_DEFINITION => [ 'name', 'directives' ],
|
||||
NodeKind::INPUT_OBJECT_TYPE_DEFINITION => [ 'name', 'directives', 'fields' ],
|
||||
NodeKind::TYPE_EXTENSION_DEFINITION => [ 'definition' ],
|
||||
NodeKind::DIRECTIVE_DEFINITION => [ 'name', 'arguments', 'locations' ]
|
||||
];
|
||||
|
||||
/**
|
||||
* Visit the AST (see class description for details)
|
||||
*
|
||||
* @api
|
||||
* @param Node $root
|
||||
* @param array $visitor
|
||||
* @param array $keyMap
|
||||
@ -335,6 +305,45 @@ class Visitor
|
||||
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
|
||||
* @return array
|
||||
|
@ -5,29 +5,6 @@ namespace GraphQL;
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
class Schema extends \GraphQL\Type\Schema
|
||||
|
@ -19,17 +19,152 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Class Helper
|
||||
* Contains functionality that could be re-used by various server implementations
|
||||
*
|
||||
* @package GraphQL\Server
|
||||
*/
|
||||
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
|
||||
* (or promise when promise adapter is different than SyncPromiseAdapter)
|
||||
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||
*
|
||||
* @api
|
||||
* @param ServerConfig $config
|
||||
* @param OperationParams $op
|
||||
*
|
||||
@ -51,6 +186,7 @@ class Helper
|
||||
* Executes batched GraphQL operations with shared promise queue
|
||||
* (thus, effectively batching deferreds|promises of all queries at once)
|
||||
*
|
||||
* @api
|
||||
* @param ServerConfig $config
|
||||
* @param OperationParams[] $operations
|
||||
* @return ExecutionResult[]|Promise
|
||||
@ -241,138 +377,9 @@ class Helper
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses HTTP request and returns GraphQL OperationParams contained in this request.
|
||||
* For batched requests it returns an array of OperationParams.
|
||||
* Send response using standard PHP `header()` and `echo`.
|
||||
*
|
||||
* This function doesn't check validity of these params.
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param Promise|ExecutionResult|ExecutionResult[] $result
|
||||
* @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
|
||||
*/
|
||||
@ -444,50 +419,6 @@ class Helper
|
||||
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
|
||||
* @return int
|
||||
@ -522,4 +453,89 @@ class Helper
|
||||
}
|
||||
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;
|
||||
|
||||
/**
|
||||
* Class QueryParams
|
||||
* Represents all available parsed query parameters
|
||||
*
|
||||
* @package GraphQL\Server
|
||||
* Structure representing parsed HTTP parameters for GraphQL operation
|
||||
*/
|
||||
class OperationParams
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* Id of the query (when using persistent queries).
|
||||
*
|
||||
* Valid aliases (case-insensitive):
|
||||
* - id
|
||||
* - queryId
|
||||
* - documentId
|
||||
*
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public $queryId;
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public $operation;
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @var array
|
||||
*/
|
||||
public $variables;
|
||||
@ -42,10 +50,10 @@ class OperationParams
|
||||
/**
|
||||
* Creates an instance from given array
|
||||
*
|
||||
* @api
|
||||
* @param array $params
|
||||
* @param bool $readonly
|
||||
*
|
||||
* @return static
|
||||
* @return OperationParams
|
||||
*/
|
||||
public static function create(array $params, $readonly = false)
|
||||
{
|
||||
@ -80,6 +88,7 @@ class OperationParams
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param string $key
|
||||
* @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
|
||||
*/
|
||||
public function isReadOnly()
|
||||
|
@ -6,10 +6,28 @@ use GraphQL\Executor\Promise\PromiseAdapter;
|
||||
use GraphQL\Type\Schema;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* @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 = [])
|
||||
{
|
||||
@ -80,14 +98,18 @@ class ServerConfig
|
||||
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
|
||||
* @return $this
|
||||
*/
|
||||
@ -98,6 +120,7 @@ class ServerConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param mixed|\Closure $rootValue
|
||||
* @return $this
|
||||
*/
|
||||
@ -107,6 +130,123 @@ class ServerConfig
|
||||
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
|
||||
*/
|
||||
@ -115,18 +255,6 @@ class ServerConfig
|
||||
return $this->rootValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set schema instance
|
||||
*
|
||||
* @param Schema $schema
|
||||
* @return $this
|
||||
*/
|
||||
public function setSchema(Schema $schema)
|
||||
{
|
||||
$this->schema = $schema;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Schema
|
||||
*/
|
||||
@ -143,30 +271,6 @@ class ServerConfig
|
||||
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
|
||||
*/
|
||||
@ -183,16 +287,6 @@ class ServerConfig
|
||||
return $this->promiseAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PromiseAdapter $promiseAdapter
|
||||
* @return $this
|
||||
*/
|
||||
public function setPromiseAdapter(PromiseAdapter $promiseAdapter)
|
||||
{
|
||||
$this->promiseAdapter = $promiseAdapter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|callable
|
||||
*/
|
||||
@ -201,25 +295,6 @@ class ServerConfig
|
||||
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
|
||||
*/
|
||||
@ -228,16 +303,6 @@ class ServerConfig
|
||||
return $this->fieldResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $fieldResolver
|
||||
* @return $this
|
||||
*/
|
||||
public function setFieldResolver(callable $fieldResolver)
|
||||
{
|
||||
$this->fieldResolver = $fieldResolver;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
@ -246,19 +311,6 @@ class ServerConfig
|
||||
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
|
||||
*/
|
||||
@ -267,18 +319,6 @@ class ServerConfig
|
||||
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
|
||||
*/
|
||||
@ -286,16 +326,4 @@ class ServerConfig
|
||||
{
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* https://github.com/graphql/express-graphql and https://github.com/apollographql/graphql-server
|
||||
* $server = new StandardServer([
|
||||
* '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
|
||||
{
|
||||
@ -30,8 +44,9 @@ class StandardServer
|
||||
private $helper;
|
||||
|
||||
/**
|
||||
* Standard GraphQL HTTP server implementation
|
||||
* Creates new instance of a standard GraphQL HTTP server
|
||||
*
|
||||
* @api
|
||||
* @param ServerConfig|array $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
@ -46,22 +61,36 @@ class StandardServer
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes GraphQL operation with given server configuration and returns execution result
|
||||
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||
* Parses HTTP request, executes and emits response (using standard PHP `header` function and `echo`)
|
||||
*
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||
* 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.
|
||||
*
|
||||
* 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);
|
||||
return $this->executeRequest($parsedBody);
|
||||
$result = $this->executeRequest($parsedBody);
|
||||
$this->helper->sendResponse($result, $exitWhenDone);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes GraphQL operation with given server configuration and returns execution result
|
||||
* (or promise when promise adapter is different from SyncPromiseAdapter)
|
||||
* Executes GraphQL operation and returns execution result
|
||||
* (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
|
||||
* @return ExecutionResult|ExecutionResult[]|Promise
|
||||
* @throws InvariantViolation
|
||||
@ -80,6 +109,12 @@ 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 ResponseInterface $response
|
||||
* @param StreamInterface $writableBodyStream
|
||||
@ -96,12 +131,28 @@ class StandardServer
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OperationParams|OperationParams[] $parsedBody
|
||||
* @param bool $exitWhenDone
|
||||
* Executes GraphQL operation and returns execution result
|
||||
* (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);
|
||||
$this->helper->sendResponse($result, $exitWhenDone);
|
||||
$parsedBody = $this->helper->parsePsrRequest($request);
|
||||
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(
|
||||
'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',
|
||||
Warning::CONFIG_DEPRECATION_WARNING,
|
||||
Warning::WARNING_CONFIG_DEPRECATION,
|
||||
E_USER_DEPRECATED
|
||||
);
|
||||
|
||||
@ -143,7 +143,7 @@ class Config
|
||||
if (!self::$allowCustomOptions) {
|
||||
Warning::warnOnce(
|
||||
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);
|
||||
|
@ -11,7 +11,7 @@ use GraphQL\Utils\Utils;
|
||||
class ListOfType extends Type implements WrappingType, OutputType, InputType
|
||||
{
|
||||
/**
|
||||
* @var callable|Type
|
||||
* @var ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
*/
|
||||
public $ofType;
|
||||
|
||||
@ -40,7 +40,7 @@ class ListOfType extends Type implements WrappingType, OutputType, InputType
|
||||
|
||||
/**
|
||||
* @param bool $recurse
|
||||
* @return mixed
|
||||
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
*/
|
||||
public function getWrappedType($recurse = false)
|
||||
{
|
||||
|
@ -11,7 +11,7 @@ use GraphQL\Utils\Utils;
|
||||
class NonNull extends Type implements WrappingType, OutputType, InputType
|
||||
{
|
||||
/**
|
||||
* @var callable|Type
|
||||
* @var ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
*/
|
||||
private $ofType;
|
||||
|
||||
@ -40,8 +40,8 @@ class NonNull extends Type implements WrappingType, OutputType, InputType
|
||||
|
||||
/**
|
||||
* @param bool $recurse
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
* @throws InvariantViolation
|
||||
*/
|
||||
public function getWrappedType($recurse = false)
|
||||
{
|
||||
|
@ -12,12 +12,15 @@ use GraphQL\Type\Schema;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Class ResolveInfo
|
||||
* @package GraphQL\Type\Definition
|
||||
* Structure containing information useful for field resolution process.
|
||||
* Passed as 3rd argument to every field resolver. See [docs on field resolving (data fetching)](data-fetching/).
|
||||
*/
|
||||
class ResolveInfo
|
||||
{
|
||||
/**
|
||||
* The name of the field being resolved
|
||||
*
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public $fieldName;
|
||||
@ -29,47 +32,74 @@ class ResolveInfo
|
||||
public $fieldASTs;
|
||||
|
||||
/**
|
||||
* AST of all nodes referencing this field in the query.
|
||||
*
|
||||
* @api
|
||||
* @var FieldNode[]
|
||||
*/
|
||||
public $fieldNodes;
|
||||
|
||||
/**
|
||||
* Expected return type of the field being resolved
|
||||
*
|
||||
* @api
|
||||
* @var ScalarType|ObjectType|InterfaceType|UnionType|EnumType|ListOfType|NonNull
|
||||
*/
|
||||
public $returnType;
|
||||
|
||||
/**
|
||||
* @var ObjectType|InterfaceType|UnionType
|
||||
* Parent type of the field being resolved
|
||||
*
|
||||
* @api
|
||||
* @var ObjectType
|
||||
*/
|
||||
public $parentType;
|
||||
|
||||
/**
|
||||
* Path to this field from the very root value
|
||||
*
|
||||
* @api
|
||||
* @var array
|
||||
*/
|
||||
public $path;
|
||||
|
||||
/**
|
||||
* Instance of a schema used for execution
|
||||
*
|
||||
* @api
|
||||
* @var Schema
|
||||
*/
|
||||
public $schema;
|
||||
|
||||
/**
|
||||
* AST of all fragments defined in query
|
||||
*
|
||||
* @api
|
||||
* @var FragmentDefinitionNode[]
|
||||
*/
|
||||
public $fragments;
|
||||
|
||||
/**
|
||||
* Root value passed to query execution
|
||||
*
|
||||
* @api
|
||||
* @var mixed
|
||||
*/
|
||||
public $rootValue;
|
||||
|
||||
/**
|
||||
* AST of operation definition node (query, mutation)
|
||||
*
|
||||
* @api
|
||||
* @var OperationDefinitionNode
|
||||
*/
|
||||
public $operation;
|
||||
|
||||
/**
|
||||
* @var array<variableName, mixed>
|
||||
* Array of variables passed to query execution
|
||||
*
|
||||
* @api
|
||||
* @var array
|
||||
*/
|
||||
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
|
||||
* @return array
|
||||
*/
|
||||
|
@ -4,16 +4,11 @@ namespace GraphQL\Type\Definition;
|
||||
use GraphQL\Error\InvariantViolation;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/*
|
||||
export type GraphQLType =
|
||||
GraphQLScalarType |
|
||||
GraphQLObjectType |
|
||||
GraphQLInterfaceType |
|
||||
GraphQLUnionType |
|
||||
GraphQLEnumType |
|
||||
GraphQLInputObjectType |
|
||||
GraphQLList |
|
||||
GraphQLNonNull;
|
||||
/**
|
||||
* Registry of standard GraphQL types
|
||||
* and a base class for all other types.
|
||||
*
|
||||
* @package GraphQL\Type\Definition
|
||||
*/
|
||||
abstract class Type implements \JsonSerializable
|
||||
{
|
||||
@ -29,6 +24,7 @@ abstract class Type implements \JsonSerializable
|
||||
private static $internalTypes;
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return IDType
|
||||
*/
|
||||
public static function id()
|
||||
@ -37,6 +33,7 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return StringType
|
||||
*/
|
||||
public static function string()
|
||||
@ -45,6 +42,7 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return BooleanType
|
||||
*/
|
||||
public static function boolean()
|
||||
@ -53,6 +51,7 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return IntType
|
||||
*/
|
||||
public static function int()
|
||||
@ -61,6 +60,7 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return FloatType
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public static function nonNull($wrappedType)
|
||||
@ -113,7 +115,8 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isInputType($type)
|
||||
@ -123,7 +126,8 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isOutputType($type)
|
||||
@ -133,6 +137,7 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param $type
|
||||
* @return bool
|
||||
*/
|
||||
@ -142,7 +147,8 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isCompositeType($type)
|
||||
@ -151,7 +157,8 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAbstractType($type)
|
||||
@ -160,8 +167,9 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return Type
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType|ListOfType
|
||||
*/
|
||||
public static function getNullableType($type)
|
||||
{
|
||||
@ -169,8 +177,9 @@ abstract class Type implements \JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return UnmodifiedType
|
||||
* @api
|
||||
* @param Type $type
|
||||
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
*/
|
||||
public static function getNamedType($type)
|
||||
{
|
||||
|
@ -1,15 +1,11 @@
|
||||
<?php
|
||||
namespace GraphQL\Type\Definition;
|
||||
|
||||
/*
|
||||
NonNullType
|
||||
ListOfType
|
||||
*/
|
||||
interface WrappingType
|
||||
{
|
||||
/**
|
||||
* @param bool $recurse
|
||||
* @return Type
|
||||
* @return ObjectType|InterfaceType|UnionType|ScalarType|InputObjectType|EnumType
|
||||
*/
|
||||
public function getWrappedType($recurse = false);
|
||||
}
|
||||
|
@ -16,29 +16,24 @@ use GraphQL\Utils\TypeInfo;
|
||||
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:
|
||||
* query, mutation (optional) and subscription (optional). A schema definition is
|
||||
* then supplied to the validator and executor.
|
||||
*
|
||||
* Example:
|
||||
* then supplied to the validator and executor. Usage Example:
|
||||
*
|
||||
* $schema = new GraphQL\Type\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:
|
||||
* Or using Schema Config instance:
|
||||
*
|
||||
* $mySchema = new GraphQL\Schema([
|
||||
* ...
|
||||
* 'directives' => array_merge(GraphQL::getInternalDirectives(), [ $myCustomDirective ]),
|
||||
* ])
|
||||
* $config = GraphQL\Type\SchemaConfig::create()
|
||||
* ->setQuery($MyAppQueryRootType)
|
||||
* ->setMutation($MyAppMutationRootType);
|
||||
*
|
||||
* $schema = new GraphQL\Type\Schema($config);
|
||||
*
|
||||
* @package GraphQL
|
||||
*/
|
||||
@ -71,9 +66,10 @@ class Schema
|
||||
/**
|
||||
* Schema constructor.
|
||||
*
|
||||
* @api
|
||||
* @param array|SchemaConfig $config
|
||||
*/
|
||||
public function __construct($config = null)
|
||||
public function __construct($config)
|
||||
{
|
||||
if (func_num_args() > 1 || $config instanceof Type) {
|
||||
trigger_error(
|
||||
@ -131,6 +127,7 @@ class Schema
|
||||
/**
|
||||
* Returns schema query type
|
||||
*
|
||||
* @api
|
||||
* @return ObjectType
|
||||
*/
|
||||
public function getQueryType()
|
||||
@ -141,6 +138,7 @@ class Schema
|
||||
/**
|
||||
* Returns schema mutation type
|
||||
*
|
||||
* @api
|
||||
* @return ObjectType|null
|
||||
*/
|
||||
public function getMutationType()
|
||||
@ -151,6 +149,7 @@ class Schema
|
||||
/**
|
||||
* Returns schema subscription
|
||||
*
|
||||
* @api
|
||||
* @return ObjectType|null
|
||||
*/
|
||||
public function getSubscriptionType()
|
||||
@ -159,6 +158,7 @@ class Schema
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
public function getConfig()
|
||||
@ -172,6 +172,7 @@ class Schema
|
||||
*
|
||||
* This operation requires full schema scan. Do not use in production environment.
|
||||
*
|
||||
* @api
|
||||
* @return Type[]
|
||||
*/
|
||||
public function getTypeMap()
|
||||
@ -186,6 +187,7 @@ class Schema
|
||||
/**
|
||||
* Returns type by it's name
|
||||
*
|
||||
* @api
|
||||
* @param string $name
|
||||
* @return Type
|
||||
*/
|
||||
@ -248,6 +250,7 @@ class Schema
|
||||
*
|
||||
* This operation requires full schema scan. Do not use in production environment.
|
||||
*
|
||||
* @api
|
||||
* @param AbstractType $abstractType
|
||||
* @return ObjectType[]
|
||||
*/
|
||||
@ -311,6 +314,7 @@ class Schema
|
||||
* Returns true if object type is concrete type of given abstract type
|
||||
* (implementation for interfaces and members of union type for unions)
|
||||
*
|
||||
* @api
|
||||
* @param AbstractType $abstractType
|
||||
* @param ObjectType $possibleType
|
||||
* @return bool
|
||||
@ -328,16 +332,18 @@ class Schema
|
||||
/**
|
||||
* Returns a list of directives supported by this schema
|
||||
*
|
||||
* @api
|
||||
* @return Directive[]
|
||||
*/
|
||||
public function getDirectives()
|
||||
{
|
||||
return $this->config->directives ?: GraphQL::getInternalDirectives();
|
||||
return $this->config->directives ?: GraphQL::getStandardDirectives();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns instance of directive by name
|
||||
*
|
||||
* @api
|
||||
* @param $name
|
||||
* @return Directive
|
||||
*/
|
||||
@ -367,6 +373,7 @@ class Schema
|
||||
*
|
||||
* This operation requires full schema scan. Do not use in production environment.
|
||||
*
|
||||
* @api
|
||||
* @throws InvariantViolation
|
||||
*/
|
||||
public function assertValid()
|
||||
|
@ -7,10 +7,18 @@ use GraphQL\Type\Definition\Type;
|
||||
use GraphQL\Utils\Utils;
|
||||
|
||||
/**
|
||||
* Class Config
|
||||
* Note: properties are marked as public for performance reasons. They should be considered read-only.
|
||||
* Schema configuration class.
|
||||
* 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
|
||||
{
|
||||
@ -46,7 +54,9 @@ class SchemaConfig
|
||||
|
||||
/**
|
||||
* Converts an array of options to instance of SchemaConfig
|
||||
* (or just returns empty config when array is not passed).
|
||||
*
|
||||
* @api
|
||||
* @param array $options
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -128,14 +138,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectType
|
||||
*/
|
||||
public function getQuery()
|
||||
{
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param ObjectType $query
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -146,14 +149,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectType
|
||||
*/
|
||||
public function getMutation()
|
||||
{
|
||||
return $this->mutation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param ObjectType $mutation
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -164,14 +160,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectType
|
||||
*/
|
||||
public function getSubscription()
|
||||
{
|
||||
return $this->subscription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param ObjectType $subscription
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -182,14 +171,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Type[]
|
||||
*/
|
||||
public function getTypes()
|
||||
{
|
||||
return $this->types ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param Type[]|callable $types
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -200,14 +182,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Directive[]
|
||||
*/
|
||||
public function getDirectives()
|
||||
{
|
||||
return $this->directives ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param Directive[] $directives
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -218,14 +193,7 @@ class SchemaConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
public function getTypeLoader()
|
||||
{
|
||||
return $this->typeLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param callable $typeLoader
|
||||
* @return SchemaConfig
|
||||
*/
|
||||
@ -234,4 +202,58 @@ class SchemaConfig
|
||||
$this->typeLoader = $typeLoader;
|
||||
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(
|
||||
'One of the schema types is not a valid type definition instance. '.
|
||||
'Try running $schema->assertValid() to find out the cause of this warning.',
|
||||
Warning::NOT_A_TYPE
|
||||
Warning::WARNING_NOT_A_TYPE
|
||||
);
|
||||
return $typeMap;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ class Utils
|
||||
$cls = get_class($obj);
|
||||
Warning::warn(
|
||||
"Trying to set non-existing property '$key' on class '$cls'",
|
||||
Warning::ASSIGN_WARNING
|
||||
Warning::WARNING_ASSIGN
|
||||
);
|
||||
}
|
||||
$obj->{$key} = $value;
|
||||
@ -437,7 +437,7 @@ class Utils
|
||||
'Name "'.$name.'" must not begin with "__", which is reserved by ' .
|
||||
'GraphQL introspection. In a future release of graphql this will ' .
|
||||
'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\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
|
||||
{
|
||||
private static $rules = [];
|
||||
@ -59,9 +77,36 @@ class DocumentValidator
|
||||
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()
|
||||
{
|
||||
@ -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
|
||||
* @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
|
||||
*/
|
||||
public static function addRule(AbstractValidationRule $rule)
|
||||
@ -155,43 +205,6 @@ class DocumentValidator
|
||||
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)
|
||||
{
|
||||
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);
|
||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||
|
||||
$expected = [
|
||||
'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);
|
||||
Warning::enable(Warning::FULL_SCHEMA_SCAN_WARNING);
|
||||
Warning::enable(Warning::WARNING_FULL_SCHEMA_SCAN);
|
||||
|
||||
$expected = [
|
||||
'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));
|
||||
$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));
|
||||
$this->assertEquals(1, count($result->errors));
|
||||
$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());
|
||||
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());
|
||||
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());
|
||||
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) {
|
||||
// Expecting parsing exception to be thrown somewhere else:
|
||||
$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()
|
||||
);
|
||||
}
|
||||
|
@ -15,13 +15,13 @@ class ConfigTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
Warning::suppress(Warning::CONFIG_DEPRECATION_WARNING);
|
||||
Warning::suppress(Warning::WARNING_CONFIG_DEPRECATION);
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass()
|
||||
{
|
||||
Config::disableValidation();
|
||||
Warning::enable(Warning::CONFIG_DEPRECATION_WARNING);
|
||||
Warning::enable(Warning::WARNING_CONFIG_DEPRECATION);
|
||||
}
|
||||
|
||||
public function testToggling()
|
||||
|
@ -122,13 +122,13 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->notInputTypes[] = $this->String;
|
||||
|
||||
Warning::suppress(Warning::NOT_A_TYPE);
|
||||
Warning::suppress(Warning::WARNING_NOT_A_TYPE);
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
parent::tearDown();
|
||||
Warning::enable(Warning::NOT_A_TYPE);
|
||||
Warning::enable(Warning::WARNING_NOT_A_TYPE);
|
||||
}
|
||||
|
||||
public function testRejectsTypesWithoutNames()
|
||||
|
Loading…
Reference in New Issue
Block a user