2015-07-15 20:05:46 +03:00
|
|
|
<?php
|
|
|
|
namespace GraphQL;
|
|
|
|
|
2016-10-21 12:39:57 +03:00
|
|
|
use GraphQL\Error\Error;
|
2016-12-03 00:11:14 +03:00
|
|
|
use GraphQL\Error\InvariantViolation;
|
2015-11-02 17:39:51 +03:00
|
|
|
use GraphQL\Executor\ExecutionResult;
|
2015-07-15 20:05:46 +03:00
|
|
|
use GraphQL\Executor\Executor;
|
2016-11-26 22:45:49 +03:00
|
|
|
use GraphQL\Executor\Promise\Promise;
|
2016-11-19 02:12:18 +03:00
|
|
|
use GraphQL\Language\AST\DocumentNode;
|
2015-07-15 20:05:46 +03:00
|
|
|
use GraphQL\Language\Parser;
|
|
|
|
use GraphQL\Language\Source;
|
2016-11-26 22:45:49 +03:00
|
|
|
use GraphQL\Executor\Promise\PromiseAdapter;
|
2016-10-18 21:34:46 +03:00
|
|
|
use GraphQL\Type\Definition\Directive;
|
2015-07-15 20:05:46 +03:00
|
|
|
use GraphQL\Validator\DocumentValidator;
|
2016-04-09 11:04:14 +03:00
|
|
|
use GraphQL\Validator\Rules\QueryComplexity;
|
2015-07-15 20:05:46 +03:00
|
|
|
|
|
|
|
class GraphQL
|
|
|
|
{
|
|
|
|
/**
|
2017-07-05 12:22:01 +03:00
|
|
|
* This is the primary entry point function for fulfilling GraphQL operations
|
|
|
|
* by parsing, validating, and executing a GraphQL document along side a
|
|
|
|
* GraphQL schema.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* schema:
|
|
|
|
* The GraphQL type system to use when validating and executing a query.
|
|
|
|
* requestString:
|
|
|
|
* 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).
|
|
|
|
* variableValues:
|
|
|
|
* A mapping of variable name to runtime value to use for all variables
|
|
|
|
* defined in the requestString.
|
|
|
|
* operationName:
|
|
|
|
* The name of the operation to use if requestString contains multiple
|
|
|
|
* possible operations. Can be omitted if requestString contains only
|
|
|
|
* one operation.
|
|
|
|
* fieldResolver:
|
|
|
|
* A resolver function to use when one is not provided by the schema.
|
|
|
|
* If not provided, the default field resolver is used (which looks for a
|
|
|
|
* value or method on the source value with the field's name).
|
2017-07-13 16:29:49 +03:00
|
|
|
* validationRules:
|
|
|
|
* A set of rules for query validation step. Default value is all available rules.
|
|
|
|
* Empty array would allow to skip query validation (may be convenient for persisted
|
|
|
|
* queries which are validated before persisting and assumed valid during execution)
|
2017-07-05 12:22:01 +03:00
|
|
|
*
|
2017-08-12 17:32:07 +03:00
|
|
|
* @param \GraphQL\Type\Schema $schema
|
2017-07-05 12:26:02 +03:00
|
|
|
* @param string|DocumentNode $source
|
2015-08-17 17:01:55 +03:00
|
|
|
* @param mixed $rootValue
|
2017-07-13 16:29:49 +03:00
|
|
|
* @param array $contextValue
|
2016-12-01 13:51:05 +03:00
|
|
|
* @param array|null $variableValues
|
2015-07-15 20:05:46 +03:00
|
|
|
* @param string|null $operationName
|
2017-07-05 12:22:01 +03:00
|
|
|
* @param callable $fieldResolver
|
2017-07-13 16:29:49 +03:00
|
|
|
* @param array $validationRules
|
2017-07-12 15:44:04 +03:00
|
|
|
* @param PromiseAdapter $promiseAdapter
|
|
|
|
*
|
2016-11-26 22:45:49 +03:00
|
|
|
* @return Promise|array
|
2015-07-15 20:05:46 +03:00
|
|
|
*/
|
2017-07-05 12:22:01 +03:00
|
|
|
public static function execute(
|
2017-08-12 17:32:07 +03:00
|
|
|
\GraphQL\Type\Schema $schema,
|
2017-07-05 12:26:02 +03:00
|
|
|
$source,
|
2017-07-05 12:22:01 +03:00
|
|
|
$rootValue = null,
|
|
|
|
$contextValue = null,
|
|
|
|
$variableValues = null,
|
|
|
|
$operationName = null,
|
2017-07-12 15:44:04 +03:00
|
|
|
callable $fieldResolver = null,
|
2017-07-13 16:29:49 +03:00
|
|
|
array $validationRules = null,
|
2017-07-12 15:44:04 +03:00
|
|
|
PromiseAdapter $promiseAdapter = null
|
2017-07-05 12:22:01 +03:00
|
|
|
)
|
2015-11-02 17:39:51 +03:00
|
|
|
{
|
2017-07-05 12:22:01 +03:00
|
|
|
$result = self::executeAndReturnResult(
|
|
|
|
$schema,
|
2017-07-05 12:26:02 +03:00
|
|
|
$source,
|
2017-07-05 12:22:01 +03:00
|
|
|
$rootValue,
|
|
|
|
$contextValue,
|
|
|
|
$variableValues,
|
|
|
|
$operationName,
|
2017-07-12 15:44:04 +03:00
|
|
|
$fieldResolver,
|
2017-07-13 16:29:49 +03:00
|
|
|
$validationRules,
|
2017-07-12 15:44:04 +03:00
|
|
|
$promiseAdapter
|
2017-07-05 12:22:01 +03:00
|
|
|
);
|
2016-11-26 22:45:49 +03:00
|
|
|
|
2016-12-01 13:51:05 +03:00
|
|
|
if ($result instanceof ExecutionResult) {
|
|
|
|
return $result->toArray();
|
|
|
|
}
|
2016-12-03 00:11:14 +03:00
|
|
|
if ($result instanceof Promise) {
|
|
|
|
return $result->then(function(ExecutionResult $executionResult) {
|
2016-12-01 13:51:05 +03:00
|
|
|
return $executionResult->toArray();
|
2016-12-03 00:11:14 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
throw new InvariantViolation("Unexpected execution result");
|
2015-11-02 17:39:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2017-07-05 12:22:01 +03:00
|
|
|
* Same as `execute`, but returns instance of ExecutionResult instead of array,
|
|
|
|
* which can be used for custom error formatting or adding extensions to response
|
|
|
|
*
|
2017-08-12 17:32:07 +03:00
|
|
|
* @param \GraphQL\Type\Schema $schema
|
2017-07-05 12:26:02 +03:00
|
|
|
* @param string|DocumentNode $source
|
2017-06-18 13:29:29 +03:00
|
|
|
* @param mixed $rootValue
|
2017-07-10 16:17:55 +03:00
|
|
|
* @param mixed $contextValue
|
2017-06-18 13:29:29 +03:00
|
|
|
* @param array|null $variableValues
|
|
|
|
* @param string|null $operationName
|
2017-07-05 12:22:01 +03:00
|
|
|
* @param callable $fieldResolver
|
2017-07-13 16:29:49 +03:00
|
|
|
* @param array $validationRules
|
2017-07-12 15:44:04 +03:00
|
|
|
* @param PromiseAdapter $promiseAdapter
|
|
|
|
*
|
2016-11-26 22:45:49 +03:00
|
|
|
* @return ExecutionResult|Promise
|
2015-11-02 17:39:51 +03:00
|
|
|
*/
|
2017-07-05 12:22:01 +03:00
|
|
|
public static function executeAndReturnResult(
|
2017-08-12 17:32:07 +03:00
|
|
|
\GraphQL\Type\Schema $schema,
|
2017-07-05 12:26:02 +03:00
|
|
|
$source,
|
2017-07-05 12:22:01 +03:00
|
|
|
$rootValue = null,
|
|
|
|
$contextValue = null,
|
|
|
|
$variableValues = null,
|
|
|
|
$operationName = null,
|
2017-07-12 15:44:04 +03:00
|
|
|
callable $fieldResolver = null,
|
2017-07-13 16:29:49 +03:00
|
|
|
array $validationRules = null,
|
2017-07-12 15:44:04 +03:00
|
|
|
PromiseAdapter $promiseAdapter = null
|
2017-07-05 12:22:01 +03:00
|
|
|
)
|
2015-07-15 20:05:46 +03:00
|
|
|
{
|
|
|
|
try {
|
2017-07-05 12:26:02 +03:00
|
|
|
if ($source instanceof DocumentNode) {
|
|
|
|
$documentNode = $source;
|
2016-05-02 00:42:05 +03:00
|
|
|
} else {
|
2017-07-05 12:26:02 +03:00
|
|
|
$documentNode = Parser::parse(new Source($source ?: '', 'GraphQL'));
|
2016-05-02 00:42:05 +03:00
|
|
|
}
|
2016-04-09 11:04:14 +03:00
|
|
|
|
|
|
|
/** @var QueryComplexity $queryComplexity */
|
|
|
|
$queryComplexity = DocumentValidator::getRule('QueryComplexity');
|
|
|
|
$queryComplexity->setRawVariableValues($variableValues);
|
|
|
|
|
2017-07-13 16:29:49 +03:00
|
|
|
$validationErrors = DocumentValidator::validate($schema, $documentNode, $validationRules);
|
2015-07-15 20:05:46 +03:00
|
|
|
|
2015-08-17 17:01:55 +03:00
|
|
|
if (!empty($validationErrors)) {
|
2015-11-02 17:39:51 +03:00
|
|
|
return new ExecutionResult(null, $validationErrors);
|
2015-07-15 20:05:46 +03:00
|
|
|
} else {
|
2017-07-05 12:22:01 +03:00
|
|
|
return Executor::execute(
|
|
|
|
$schema,
|
|
|
|
$documentNode,
|
|
|
|
$rootValue,
|
|
|
|
$contextValue,
|
|
|
|
$variableValues,
|
|
|
|
$operationName,
|
2017-07-12 15:44:04 +03:00
|
|
|
$fieldResolver,
|
|
|
|
$promiseAdapter
|
2017-07-05 12:22:01 +03:00
|
|
|
);
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
2015-08-17 17:01:55 +03:00
|
|
|
} catch (Error $e) {
|
2015-11-02 17:39:51 +03:00
|
|
|
return new ExecutionResult(null, [$e]);
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|
|
|
|
}
|
2016-10-18 21:34:46 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public static function getInternalDirectives()
|
|
|
|
{
|
|
|
|
return array_values(Directive::getInternalDirectives());
|
|
|
|
}
|
2016-11-26 22:45:49 +03:00
|
|
|
|
2016-12-14 16:18:10 +03:00
|
|
|
/**
|
|
|
|
* @param callable $fn
|
|
|
|
*/
|
|
|
|
public static function setDefaultFieldResolver(callable $fn)
|
|
|
|
{
|
|
|
|
Executor::setDefaultFieldResolver($fn);
|
|
|
|
}
|
|
|
|
|
2016-11-26 22:45:49 +03:00
|
|
|
/**
|
|
|
|
* @param PromiseAdapter|null $promiseAdapter
|
|
|
|
*/
|
|
|
|
public static function setPromiseAdapter(PromiseAdapter $promiseAdapter = null)
|
|
|
|
{
|
|
|
|
Executor::setPromiseAdapter($promiseAdapter);
|
|
|
|
}
|
2015-07-15 20:05:46 +03:00
|
|
|
}
|