Improved docblock comments (suitable for reference docs generation)

This commit is contained in:
Vladimir Razuvaev 2017-08-19 23:01:46 +07:00
parent 3ef2d2827b
commit 1b4f983f3f
35 changed files with 1024 additions and 742 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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()

View File

@ -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
*/

View File

@ -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)

View File

@ -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
{

View File

@ -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
*/

View File

@ -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);

View File

@ -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);

View File

@ -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()
{

View File

@ -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

View File

@ -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
*/

View File

@ -15,44 +15,95 @@ class VisitorOperation
public $removeNode;
}
/**
* Utility for efficient AST traversal and modification.
*
* `visit()` will walk through an AST using a depth first traversal, calling
* the visitor's enter function at each node in the traversal, and calling the
* leave function after visiting that node and all of it's child nodes.
*
* By returning different values from the enter and leave functions, the
* behavior of the visitor can be altered, including skipping over a sub-tree of
* the AST (by returning false), editing the AST by returning a value or null
* to remove the value, or to stop the whole traversal by returning BREAK.
*
* When using `visit()` to edit an AST, the original AST will not be modified, and
* a new version of the AST with the changes applied will be returned from the
* visit function.
*
* $editedAST = Visitor::visit($ast, [
* 'enter' => function ($node, $key, $parent, $path, $ancestors) {
* // return
* // null: no action
* // Visitor::skipNode(): skip visiting this node
* // Visitor::stop(): stop visiting altogether
* // Visitor::removeNode(): delete this node
* // any value: replace this node with the returned value
* },
* 'leave' => function ($node, $key, $parent, $path, $ancestors) {
* // return
* // null: no action
* // Visitor::stop(): stop visiting altogether
* // Visitor::removeNode(): delete this node
* // any value: replace this node with the returned value
* }
* ]);
*
* Alternatively to providing enter() and leave() functions, a visitor can
* instead provide functions named the same as the [kinds of AST nodes](reference/#graphqllanguageastnodekind),
* or enter/leave visitors at a named key, leading to four permutations of
* visitor API:
*
* 1) Named visitors triggered when entering a node a specific kind.
*
* Visitor::visit($ast, [
* 'Kind' => function ($node) {
* // enter the "Kind" node
* }
* ]);
*
* 2) Named visitors that trigger upon entering and leaving a node of
* a specific kind.
*
* Visitor::visit($ast, [
* 'Kind' => [
* 'enter' => function ($node) {
* // enter the "Kind" node
* }
* 'leave' => function ($node) {
* // leave the "Kind" node
* }
* ]
* ]);
*
* 3) Generic visitors that trigger upon entering and leaving any node.
*
* Visitor::visit($ast, [
* 'enter' => function ($node) {
* // enter any node
* },
* 'leave' => function ($node) {
* // leave any node
* }
* ]);
*
* 4) Parallel visitors for entering and leaving nodes of a specific kind.
*
* Visitor::visit($ast, [
* 'enter' => [
* 'Kind' => function($node) {
* // enter the "Kind" node
* }
* },
* 'leave' => [
* 'Kind' => function ($node) {
* // leave the "Kind" node
* }
* ]
* ]);
*/
class Visitor
{
/**
* Returns marker for visitor break
*
* @return VisitorOperation
*/
public static function stop()
{
$r = new VisitorOperation();
$r->doBreak = true;
return $r;
}
/**
* Returns marker for skipping current node
*
* @return VisitorOperation
*/
public static function skipNode()
{
$r = new VisitorOperation();
$r->doContinue = true;
return $r;
}
/**
* Returns marker for removing a node
*
* @return VisitorOperation
*/
public static function removeNode()
{
$r = new VisitorOperation();
$r->removeNode = true;
return $r;
}
public static $visitorKeys = [
NodeKind::NAME => [],
NodeKind::DOCUMENT => ['definitions'],
@ -96,90 +147,9 @@ class Visitor
];
/**
* visit() will walk through an AST using a depth first traversal, calling
* the visitor's enter function at each node in the traversal, and calling the
* leave function after visiting that node and all of it's child nodes.
*
* By returning different values from the enter and leave functions, the
* behavior of the visitor can be altered, including skipping over a sub-tree of
* the AST (by returning false), editing the AST by returning a value or null
* to remove the value, or to stop the whole traversal by returning BREAK.
*
* When using visit() to edit an AST, the original AST will not be modified, and
* a new version of the AST with the changes applied will be returned from the
* visit function.
*
* $editedAST = Visitor::visit($ast, [
* 'enter' => function ($node, $key, $parent, $path, $ancestors) {
* // return
* // null: no action
* // Visitor::skipNode(): skip visiting this node
* // Visitor::stop(): stop visiting altogether
* // Visitor::removeNode(): delete this node
* // any value: replace this node with the returned value
* },
* 'leave' => function ($node, $key, $parent, $path, $ancestors) {
* // return
* // null: no action
* // Visitor::stop(): stop visiting altogether
* // Visitor::removeNode(): delete this node
* // any value: replace this node with the returned value
* }
* ]);
*
* Alternatively to providing enter() and leave() functions, a visitor can
* instead provide functions named the same as the kinds of AST nodes, or
* enter/leave visitors at a named key, leading to four permutations of
* visitor API:
*
* 1) Named visitors triggered when entering a node a specific kind.
*
* Visitor::visit($ast, [
* 'Kind' => function ($node) {
* // enter the "Kind" node
* }
* ]);
*
* 2) Named visitors that trigger upon entering and leaving a node of
* a specific kind.
*
* Visitor::visit($ast, [
* 'Kind' => [
* 'enter' => function ($node) {
* // enter the "Kind" node
* }
* 'leave' => function ($node) {
* // leave the "Kind" node
* }
* ]
* ]);
*
* 3) Generic visitors that trigger upon entering and leaving any node.
*
* Visitor::visit($ast, [
* 'enter' => function ($node) {
* // enter any node
* },
* 'leave' => function ($node) {
* // leave any node
* }
* ]);
*
* 4) Parallel visitors for entering and leaving nodes of a specific kind.
*
* Visitor::visit($ast, [
* 'enter' => [
* 'Kind' => function($node) {
* // enter the "Kind" node
* }
* },
* 'leave' => [
* 'Kind' => function ($node) {
* // leave the "Kind" node
* }
* ]
* ]);
* 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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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()

View File

@ -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;
}
}

View File

@ -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
@ -79,7 +108,13 @@ class StandardServer
}
}
/**
/**
* Executes PSR-7 request and fulfills PSR-7 response.
*
* See `executePsrRequest()` if you prefer to create response yourself
* (e.g. using specific JsonResponse instance of some framework).
*
* @api
* @param ServerRequestInterface $request
* @param 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;
}
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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
*/

View File

@ -4,17 +4,12 @@ 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
{
const STRING = 'String';
@ -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)
{

View File

@ -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);
}

View File

@ -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()

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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
);
}

View File

@ -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)

View File

@ -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' => [

View File

@ -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());

View File

@ -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);
}
/**

View File

@ -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()
);
}

View File

@ -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()

View File

@ -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()