mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 06:16:05 +03:00
Merge branch 'master' into root-value-consistent-naming
# Conflicts: # docs/data-fetching.md # src/Executor/Executor.php # tests/Executor/DeferredFieldsTest.php
This commit is contained in:
commit
d037ab7ec3
@ -118,7 +118,9 @@ function defaultFieldResolver($rootValue, $args, $context, \GraphQL\Type\Definit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $property instanceof Closure ? $property($rootValue, $args, $context, $info) : $property;
|
return $property instanceof Closure
|
||||||
|
? $property($rootValue, $args, $context, $info)
|
||||||
|
: $property;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ static function getNullableType($type)
|
|||||||
```
|
```
|
||||||
# GraphQL\Type\Definition\ResolveInfo
|
# GraphQL\Type\Definition\ResolveInfo
|
||||||
Structure containing information useful for field resolution process.
|
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.md).
|
Passed as 4th argument to every field resolver. See [docs on field resolving (data fetching)](data-fetching.md).
|
||||||
|
|
||||||
**Class Props:**
|
**Class Props:**
|
||||||
```php
|
```php
|
||||||
|
@ -14,7 +14,7 @@ use GraphQL\Type\Schema;
|
|||||||
* Data that must be available at all points during query execution.
|
* Data that must be available at all points during query execution.
|
||||||
*
|
*
|
||||||
* Namely, schema of the type system that is currently executing,
|
* Namely, schema of the type system that is currently executing,
|
||||||
* and the fragments defined in the query document
|
* and the fragments defined in the query document.
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -45,7 +45,7 @@ class ExecutionContext
|
|||||||
public $errors;
|
public $errors;
|
||||||
|
|
||||||
/** @var PromiseAdapter */
|
/** @var PromiseAdapter */
|
||||||
public $promises;
|
public $promiseAdapter;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
$schema,
|
$schema,
|
||||||
@ -53,7 +53,7 @@ class ExecutionContext
|
|||||||
$rootValue,
|
$rootValue,
|
||||||
$contextValue,
|
$contextValue,
|
||||||
$operation,
|
$operation,
|
||||||
$variables,
|
$variableValues,
|
||||||
$errors,
|
$errors,
|
||||||
$fieldResolver,
|
$fieldResolver,
|
||||||
$promiseAdapter
|
$promiseAdapter
|
||||||
@ -63,10 +63,10 @@ class ExecutionContext
|
|||||||
$this->rootValue = $rootValue;
|
$this->rootValue = $rootValue;
|
||||||
$this->contextValue = $contextValue;
|
$this->contextValue = $contextValue;
|
||||||
$this->operation = $operation;
|
$this->operation = $operation;
|
||||||
$this->variableValues = $variables;
|
$this->variableValues = $variableValues;
|
||||||
$this->errors = $errors ?: [];
|
$this->errors = $errors ?: [];
|
||||||
$this->fieldResolver = $fieldResolver;
|
$this->fieldResolver = $fieldResolver;
|
||||||
$this->promises = $promiseAdapter;
|
$this->promiseAdapter = $promiseAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addError(Error $error)
|
public function addError(Error $error)
|
||||||
|
@ -182,6 +182,8 @@ class Executor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $property instanceof Closure ? $property($rootValue, $args, $context, $info) : $property;
|
return $property instanceof Closure
|
||||||
|
? $property($rootValue, $args, $context, $info)
|
||||||
|
: $property;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
public function doExecute() : Promise
|
public function doExecute() : Promise
|
||||||
{
|
{
|
||||||
// Return a Promise that will eventually resolve to the data described by
|
// Return a Promise that will eventually resolve to the data described by
|
||||||
// The "Response" section of the GraphQL specification.
|
// the "Response" section of the GraphQL specification.
|
||||||
//
|
//
|
||||||
// If errors are encountered while executing a GraphQL field, only that
|
// If errors are encountered while executing a GraphQL field, only that
|
||||||
// field and its descendants will be omitted, and sibling fields will still
|
// field and its descendants will be omitted, and sibling fields will still
|
||||||
@ -212,7 +212,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
// But for the "sync" case it is always fulfilled
|
// But for the "sync" case it is always fulfilled
|
||||||
return $this->isPromise($result)
|
return $this->isPromise($result)
|
||||||
? $result
|
? $result
|
||||||
: $this->exeContext->promises->createFulfilled($result);
|
: $this->exeContext->promiseAdapter->createFulfilled($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -252,9 +252,9 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
//
|
//
|
||||||
// Similar to completeValueCatchingError.
|
// Similar to completeValueCatchingError.
|
||||||
try {
|
try {
|
||||||
$result = $operation->operation === 'mutation' ?
|
$result = $operation->operation === 'mutation'
|
||||||
$this->executeFieldsSerially($type, $rootValue, $path, $fields) :
|
? $this->executeFieldsSerially($type, $rootValue, $path, $fields)
|
||||||
$this->executeFields($type, $rootValue, $path, $fields);
|
: $this->executeFields($type, $rootValue, $path, $fields);
|
||||||
if ($this->isPromise($result)) {
|
if ($this->isPromise($result)) {
|
||||||
return $result->then(
|
return $result->then(
|
||||||
null,
|
null,
|
||||||
@ -262,7 +262,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
if ($error instanceof Error) {
|
if ($error instanceof Error) {
|
||||||
$this->exeContext->addError($error);
|
$this->exeContext->addError($error);
|
||||||
|
|
||||||
return $this->exeContext->promises->createFulfilled(null);
|
return $this->exeContext->promiseAdapter->createFulfilled(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -527,7 +527,11 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
return self::$UNDEFINED;
|
return self::$UNDEFINED;
|
||||||
}
|
}
|
||||||
$returnType = $fieldDef->getType();
|
$returnType = $fieldDef->getType();
|
||||||
// The resolve function's optional third argument is a collection of
|
// The resolve function's optional 3rd argument is a context value that
|
||||||
|
// is provided to every resolve function within an execution. It is commonly
|
||||||
|
// used to represent an authenticated user, or request-specific caches.
|
||||||
|
$context = $exeContext->contextValue;
|
||||||
|
// The resolve function's optional 4th argument is a collection of
|
||||||
// information about the current execution state.
|
// information about the current execution state.
|
||||||
$info = new ResolveInfo(
|
$info = new ResolveInfo(
|
||||||
$fieldName,
|
$fieldName,
|
||||||
@ -548,10 +552,6 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
} else {
|
} else {
|
||||||
$resolveFn = $this->exeContext->fieldResolver;
|
$resolveFn = $this->exeContext->fieldResolver;
|
||||||
}
|
}
|
||||||
// The resolve function's optional third argument is a context value that
|
|
||||||
// is provided to every resolve function within an execution. It is commonly
|
|
||||||
// used to represent an authenticated user, or request-specific caches.
|
|
||||||
$context = $exeContext->contextValue;
|
|
||||||
// Get the resolve function, regardless of if its result is normal
|
// Get the resolve function, regardless of if its result is normal
|
||||||
// or abrupt (error).
|
// or abrupt (error).
|
||||||
$result = $this->resolveOrError(
|
$result = $this->resolveOrError(
|
||||||
@ -575,6 +575,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This method looks up the field on the given type definition.
|
* This method looks up the field on the given type definition.
|
||||||
|
*
|
||||||
* It has special casing for the two introspection fields, __schema
|
* It has special casing for the two introspection fields, __schema
|
||||||
* and __typename. __typename is special because it can always be
|
* and __typename. __typename is special because it can always be
|
||||||
* queried as a field, even in situations where no other fields
|
* queried as a field, even in situations where no other fields
|
||||||
@ -609,8 +610,8 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Isolates the "ReturnOrAbrupt" behavior to not de-opt the `resolveField`
|
* Isolates the "ReturnOrAbrupt" behavior to not de-opt the `resolveField` function.
|
||||||
* function. Returns the result of resolveFn or the abrupt-return Error object.
|
* Returns the result of resolveFn or the abrupt-return Error object.
|
||||||
*
|
*
|
||||||
* @param FieldDefinition $fieldDef
|
* @param FieldDefinition $fieldDef
|
||||||
* @param FieldNode $fieldNode
|
* @param FieldNode $fieldNode
|
||||||
@ -624,7 +625,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
private function resolveOrError($fieldDef, $fieldNode, $resolveFn, $rootValue, $context, $info)
|
private function resolveOrError($fieldDef, $fieldNode, $resolveFn, $rootValue, $context, $info)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
// Build hash of arguments from the field.arguments AST, using the
|
// Build a map of arguments from the field.arguments AST, using the
|
||||||
// variables scope to fulfill any variable references.
|
// variables scope to fulfill any variable references.
|
||||||
$args = Values::getArgumentValues(
|
$args = Values::getArgumentValues(
|
||||||
$fieldDef,
|
$fieldDef,
|
||||||
@ -686,7 +687,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
function ($error) use ($exeContext) {
|
function ($error) use ($exeContext) {
|
||||||
$exeContext->addError($error);
|
$exeContext->addError($error);
|
||||||
|
|
||||||
return $this->exeContext->promises->createFulfilled(null);
|
return $this->exeContext->promiseAdapter->createFulfilled(null);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -733,7 +734,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
return $promise->then(
|
return $promise->then(
|
||||||
null,
|
null,
|
||||||
function ($error) use ($fieldNodes, $path) {
|
function ($error) use ($fieldNodes, $path) {
|
||||||
return $this->exeContext->promises->createRejected(Error::createLocatedError(
|
return $this->exeContext->promiseAdapter->createRejected(Error::createLocatedError(
|
||||||
$error,
|
$error,
|
||||||
$fieldNodes,
|
$fieldNodes,
|
||||||
$path
|
$path
|
||||||
@ -865,7 +866,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
*/
|
*/
|
||||||
private function isPromise($value)
|
private function isPromise($value)
|
||||||
{
|
{
|
||||||
return $value instanceof Promise || $this->exeContext->promises->isThenable($value);
|
return $value instanceof Promise || $this->exeContext->promiseAdapter->isThenable($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -881,12 +882,12 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
if ($value === null || $value instanceof Promise) {
|
if ($value === null || $value instanceof Promise) {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
if ($this->exeContext->promises->isThenable($value)) {
|
if ($this->exeContext->promiseAdapter->isThenable($value)) {
|
||||||
$promise = $this->exeContext->promises->convertThenable($value);
|
$promise = $this->exeContext->promiseAdapter->convertThenable($value);
|
||||||
if (! $promise instanceof Promise) {
|
if (! $promise instanceof Promise) {
|
||||||
throw new InvariantViolation(sprintf(
|
throw new InvariantViolation(sprintf(
|
||||||
'%s::convertThenable is expected to return instance of GraphQL\Executor\Promise\Promise, got: %s',
|
'%s::convertThenable is expected to return instance of GraphQL\Executor\Promise\Promise, got: %s',
|
||||||
get_class($this->exeContext->promises),
|
get_class($this->exeContext->promiseAdapter),
|
||||||
Utils::printSafe($promise)
|
Utils::printSafe($promise)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -928,28 +929,27 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Complete a list value by completing each item in the list with the
|
* Complete a list value by completing each item in the list with the inner type.
|
||||||
* inner type
|
|
||||||
*
|
*
|
||||||
* @param FieldNode[] $fieldNodes
|
* @param FieldNode[] $fieldNodes
|
||||||
* @param mixed[] $path
|
* @param mixed[] $path
|
||||||
* @param mixed $result
|
* @param mixed[]|Traversable $results
|
||||||
*
|
*
|
||||||
* @return mixed[]|Promise
|
* @return mixed[]|Promise
|
||||||
*
|
*
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function completeListValue(ListOfType $returnType, $fieldNodes, ResolveInfo $info, $path, &$result)
|
private function completeListValue(ListOfType $returnType, $fieldNodes, ResolveInfo $info, $path, &$results)
|
||||||
{
|
{
|
||||||
$itemType = $returnType->getWrappedType();
|
$itemType = $returnType->getWrappedType();
|
||||||
Utils::invariant(
|
Utils::invariant(
|
||||||
is_array($result) || $result instanceof Traversable,
|
is_array($results) || $results instanceof Traversable,
|
||||||
'User Error: expected iterable, but did not find one for field ' . $info->parentType . '.' . $info->fieldName . '.'
|
'User Error: expected iterable, but did not find one for field ' . $info->parentType . '.' . $info->fieldName . '.'
|
||||||
);
|
);
|
||||||
$containsPromise = false;
|
$containsPromise = false;
|
||||||
$i = 0;
|
$i = 0;
|
||||||
$completedItems = [];
|
$completedItems = [];
|
||||||
foreach ($result as $item) {
|
foreach ($results as $item) {
|
||||||
$fieldPath = $path;
|
$fieldPath = $path;
|
||||||
$fieldPath[] = $i++;
|
$fieldPath[] = $i++;
|
||||||
$info->path = $fieldPath;
|
$info->path = $fieldPath;
|
||||||
@ -960,7 +960,9 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
$completedItems[] = $completedItem;
|
$completedItems[] = $completedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $containsPromise ? $this->exeContext->promises->all($completedItems) : $completedItems;
|
return $containsPromise
|
||||||
|
? $this->exeContext->promiseAdapter->all($completedItems)
|
||||||
|
: $completedItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1102,7 +1104,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! empty($promisedIsTypeOfResults)) {
|
if (! empty($promisedIsTypeOfResults)) {
|
||||||
return $this->exeContext->promises->all($promisedIsTypeOfResults)
|
return $this->exeContext->promiseAdapter->all($promisedIsTypeOfResults)
|
||||||
->then(static function ($isTypeOfResults) use ($possibleTypes) {
|
->then(static function ($isTypeOfResults) use ($possibleTypes) {
|
||||||
foreach ($isTypeOfResults as $index => $result) {
|
foreach ($isTypeOfResults as $index => $result) {
|
||||||
if ($result) {
|
if ($result) {
|
||||||
@ -1188,7 +1190,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
/**
|
/**
|
||||||
* @param FieldNode[] $fieldNodes
|
* @param FieldNode[] $fieldNodes
|
||||||
* @param mixed[] $path
|
* @param mixed[] $path
|
||||||
* @param mixed[] $result
|
* @param mixed $result
|
||||||
*
|
*
|
||||||
* @return mixed[]|Promise|stdClass
|
* @return mixed[]|Promise|stdClass
|
||||||
*
|
*
|
||||||
@ -1300,7 +1302,7 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
{
|
{
|
||||||
$keys = array_keys($assoc);
|
$keys = array_keys($assoc);
|
||||||
$valuesAndPromises = array_values($assoc);
|
$valuesAndPromises = array_values($assoc);
|
||||||
$promise = $this->exeContext->promises->all($valuesAndPromises);
|
$promise = $this->exeContext->promiseAdapter->all($valuesAndPromises);
|
||||||
|
|
||||||
return $promise->then(static function ($values) use ($keys) {
|
return $promise->then(static function ($values) use ($keys) {
|
||||||
$resolvedResults = [];
|
$resolvedResults = [];
|
||||||
@ -1325,9 +1327,9 @@ class ReferenceExecutor implements ExecutorImplementation
|
|||||||
ResolveInfo $info,
|
ResolveInfo $info,
|
||||||
&$result
|
&$result
|
||||||
) {
|
) {
|
||||||
$runtimeType = is_string($runtimeTypeOrName) ?
|
$runtimeType = is_string($runtimeTypeOrName)
|
||||||
$this->exeContext->schema->getType($runtimeTypeOrName) :
|
? $this->exeContext->schema->getType($runtimeTypeOrName)
|
||||||
$runtimeTypeOrName;
|
: $runtimeTypeOrName;
|
||||||
if (! $runtimeType instanceof ObjectType) {
|
if (! $runtimeType instanceof ObjectType) {
|
||||||
throw new InvariantViolation(
|
throw new InvariantViolation(
|
||||||
sprintf(
|
sprintf(
|
||||||
|
@ -273,6 +273,7 @@ class Values
|
|||||||
return $error->getMessage();
|
return $error->getMessage();
|
||||||
},
|
},
|
||||||
$errors
|
$errors
|
||||||
) : [];
|
)
|
||||||
|
: [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,7 +821,10 @@ class CoroutineExecutor implements Runtime, ExecutorImplementation
|
|||||||
} else {
|
} else {
|
||||||
$childContexts = [];
|
$childContexts = [];
|
||||||
|
|
||||||
foreach ($this->collector->collectFields($objectType, $ctx->shared->mergedSelectionSet ?? $this->mergeSelectionSets($ctx)) as $childShared) {
|
foreach ($this->collector->collectFields(
|
||||||
|
$objectType,
|
||||||
|
$ctx->shared->mergedSelectionSet ?? $this->mergeSelectionSets($ctx)
|
||||||
|
) as $childShared) {
|
||||||
/** @var CoroutineContextShared $childShared */
|
/** @var CoroutineContextShared $childShared */
|
||||||
|
|
||||||
$childPath = $path;
|
$childPath = $path;
|
||||||
|
@ -512,15 +512,15 @@ class Parser
|
|||||||
*/
|
*/
|
||||||
private function parseVariableDefinitions()
|
private function parseVariableDefinitions()
|
||||||
{
|
{
|
||||||
return $this->peek(Token::PAREN_L) ?
|
return $this->peek(Token::PAREN_L)
|
||||||
$this->many(
|
? $this->many(
|
||||||
Token::PAREN_L,
|
Token::PAREN_L,
|
||||||
function () {
|
function () {
|
||||||
return $this->parseVariableDefinition();
|
return $this->parseVariableDefinition();
|
||||||
},
|
},
|
||||||
Token::PAREN_R
|
Token::PAREN_R
|
||||||
) :
|
)
|
||||||
new NodeList([]);
|
: new NodeList([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -592,9 +592,9 @@ class Parser
|
|||||||
*/
|
*/
|
||||||
private function parseSelection()
|
private function parseSelection()
|
||||||
{
|
{
|
||||||
return $this->peek(Token::SPREAD) ?
|
return $this->peek(Token::SPREAD)
|
||||||
$this->parseFragment() :
|
? $this->parseFragment()
|
||||||
$this->parseField();
|
: $this->parseField();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -634,17 +634,17 @@ class Parser
|
|||||||
*/
|
*/
|
||||||
private function parseArguments($isConst)
|
private function parseArguments($isConst)
|
||||||
{
|
{
|
||||||
$parseFn = $isConst ?
|
$parseFn = $isConst
|
||||||
function () {
|
? function () {
|
||||||
return $this->parseConstArgument();
|
return $this->parseConstArgument();
|
||||||
} :
|
}
|
||||||
function () {
|
: function () {
|
||||||
return $this->parseArgument();
|
return $this->parseArgument();
|
||||||
};
|
};
|
||||||
|
|
||||||
return $this->peek(Token::PAREN_L) ?
|
return $this->peek(Token::PAREN_L)
|
||||||
$this->many(Token::PAREN_L, $parseFn, Token::PAREN_R) :
|
? $this->many(Token::PAREN_L, $parseFn, Token::PAREN_R)
|
||||||
new NodeList([]);
|
: new NodeList([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1545,7 +1545,8 @@ class Parser
|
|||||||
Token::BRACE_L,
|
Token::BRACE_L,
|
||||||
[$this, 'parseOperationTypeDefinition'],
|
[$this, 'parseOperationTypeDefinition'],
|
||||||
Token::BRACE_R
|
Token::BRACE_R
|
||||||
) : [];
|
)
|
||||||
|
: [];
|
||||||
if (count($directives) === 0 && count($operationTypes) === 0) {
|
if (count($directives) === 0 && count($operationTypes) === 0) {
|
||||||
$this->unexpected();
|
$this->unexpected();
|
||||||
}
|
}
|
||||||
|
@ -251,8 +251,18 @@ class Visitor
|
|||||||
$inArray = $stack['inArray'];
|
$inArray = $stack['inArray'];
|
||||||
$stack = $stack['prev'];
|
$stack = $stack['prev'];
|
||||||
} else {
|
} else {
|
||||||
$key = $parent !== null ? ($inArray ? $index : $keys[$index]) : $UNDEFINED;
|
$key = $parent !== null
|
||||||
$node = $parent !== null ? ($parent instanceof NodeList || is_array($parent) ? $parent[$key] : $parent->{$key}) : $newRoot;
|
? ($inArray
|
||||||
|
? $index
|
||||||
|
: $keys[$index]
|
||||||
|
)
|
||||||
|
: $UNDEFINED;
|
||||||
|
$node = $parent !== null
|
||||||
|
? ($parent instanceof NodeList || is_array($parent)
|
||||||
|
? $parent[$key]
|
||||||
|
: $parent->{$key}
|
||||||
|
)
|
||||||
|
: $newRoot;
|
||||||
if ($node === null || $node === $UNDEFINED) {
|
if ($node === null || $node === $UNDEFINED) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,14 @@ class Helper
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stripos($contentType, 'application/graphql') !== false) {
|
if (stripos($contentType, 'application/graphql') !== false) {
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
$rawBody = $readRawBodyFn
|
||||||
|
? $readRawBodyFn()
|
||||||
|
: $this->readRawBody();
|
||||||
$bodyParams = ['query' => $rawBody ?: ''];
|
$bodyParams = ['query' => $rawBody ?: ''];
|
||||||
} elseif (stripos($contentType, 'application/json') !== false) {
|
} elseif (stripos($contentType, 'application/json') !== false) {
|
||||||
$rawBody = $readRawBodyFn ? $readRawBodyFn() : $this->readRawBody();
|
$rawBody = $readRawBodyFn ?
|
||||||
|
$readRawBodyFn()
|
||||||
|
: $this->readRawBody();
|
||||||
$bodyParams = json_decode($rawBody ?: '', true);
|
$bodyParams = json_decode($rawBody ?: '', true);
|
||||||
|
|
||||||
if (json_last_error()) {
|
if (json_last_error()) {
|
||||||
@ -272,7 +276,9 @@ class Helper
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$doc = $op->queryId ? $this->loadPersistedQuery($config, $op) : $op->query;
|
$doc = $op->queryId
|
||||||
|
? $this->loadPersistedQuery($config, $op)
|
||||||
|
: $op->query;
|
||||||
|
|
||||||
if (! $doc instanceof DocumentNode) {
|
if (! $doc instanceof DocumentNode) {
|
||||||
$doc = Parser::parse($doc);
|
$doc = Parser::parse($doc);
|
||||||
|
@ -20,11 +20,14 @@ class BooleanType extends ScalarType
|
|||||||
public $description = 'The `Boolean` scalar type represents `true` or `false`.';
|
public $description = 'The `Boolean` scalar type represents `true` or `false`.';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $value
|
* Coerce the given value to a boolean.
|
||||||
*
|
*
|
||||||
* @return bool
|
* The GraphQL spec leaves this up to the implementations, so we just do what
|
||||||
|
* PHP does natively to make this intuitive for developers.
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
*/
|
*/
|
||||||
public function serialize($value)
|
public function serialize($value) : bool
|
||||||
{
|
{
|
||||||
return (bool) $value;
|
return (bool) $value;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,9 @@ class InputObjectType extends Type implements InputType, NullableType, NamedType
|
|||||||
if ($this->fields === null) {
|
if ($this->fields === null) {
|
||||||
$this->fields = [];
|
$this->fields = [];
|
||||||
$fields = $this->config['fields'] ?? [];
|
$fields = $this->config['fields'] ?? [];
|
||||||
$fields = is_callable($fields) ? call_user_func($fields) : $fields;
|
$fields = is_callable($fields)
|
||||||
|
? call_user_func($fields)
|
||||||
|
: $fields;
|
||||||
|
|
||||||
if (! is_array($fields)) {
|
if (! is_array($fields)) {
|
||||||
throw new InvariantViolation(
|
throw new InvariantViolation(
|
||||||
|
@ -31,6 +31,8 @@ class ListOfType extends Type implements WrappingType, OutputType, NullableType,
|
|||||||
{
|
{
|
||||||
$type = $this->ofType;
|
$type = $this->ofType;
|
||||||
|
|
||||||
return $recurse && $type instanceof WrappingType ? $type->getWrappedType($recurse) : $type;
|
return $recurse && $type instanceof WrappingType
|
||||||
|
? $type->getWrappedType($recurse)
|
||||||
|
: $type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,8 @@ class NonNull extends Type implements WrappingType, OutputType, InputType
|
|||||||
{
|
{
|
||||||
$type = $this->ofType;
|
$type = $this->ofType;
|
||||||
|
|
||||||
return $recurse && $type instanceof WrappingType ? $type->getWrappedType($recurse) : $type;
|
return $recurse && $type instanceof WrappingType
|
||||||
|
? $type->getWrappedType($recurse)
|
||||||
|
: $type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,9 @@ class ObjectType extends Type implements OutputType, CompositeType, NullableType
|
|||||||
{
|
{
|
||||||
if ($this->interfaces === null) {
|
if ($this->interfaces === null) {
|
||||||
$interfaces = $this->config['interfaces'] ?? [];
|
$interfaces = $this->config['interfaces'] ?? [];
|
||||||
$interfaces = is_callable($interfaces) ? call_user_func($interfaces) : $interfaces;
|
$interfaces = is_callable($interfaces)
|
||||||
|
? call_user_func($interfaces)
|
||||||
|
: $interfaces;
|
||||||
|
|
||||||
if ($interfaces !== null && ! is_array($interfaces)) {
|
if ($interfaces !== null && ! is_array($interfaces)) {
|
||||||
throw new InvariantViolation(
|
throw new InvariantViolation(
|
||||||
@ -207,12 +209,14 @@ class ObjectType extends Type implements OutputType, CompositeType, NullableType
|
|||||||
*/
|
*/
|
||||||
public function isTypeOf($value, $context, ResolveInfo $info)
|
public function isTypeOf($value, $context, ResolveInfo $info)
|
||||||
{
|
{
|
||||||
return isset($this->config['isTypeOf']) ? call_user_func(
|
return isset($this->config['isTypeOf'])
|
||||||
|
? call_user_func(
|
||||||
$this->config['isTypeOf'],
|
$this->config['isTypeOf'],
|
||||||
$value,
|
$value,
|
||||||
$context,
|
$context,
|
||||||
$info
|
$info
|
||||||
) : null;
|
)
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,12 +15,13 @@ use function array_merge_recursive;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Structure containing information useful for field resolution process.
|
* 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.md).
|
*
|
||||||
|
* Passed as 4th argument to every field resolver. See [docs on field resolving (data fetching)](data-fetching.md).
|
||||||
*/
|
*/
|
||||||
class ResolveInfo
|
class ResolveInfo
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The name of the field being resolved
|
* The name of the field being resolved.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var string
|
* @var string
|
||||||
@ -36,7 +37,7 @@ class ResolveInfo
|
|||||||
public $fieldNodes = [];
|
public $fieldNodes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expected return type of the field being resolved
|
* Expected return type of the field being resolved.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var ScalarType|ObjectType|InterfaceType|UnionType|EnumType|ListOfType|NonNull
|
* @var ScalarType|ObjectType|InterfaceType|UnionType|EnumType|ListOfType|NonNull
|
||||||
@ -44,7 +45,7 @@ class ResolveInfo
|
|||||||
public $returnType;
|
public $returnType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parent type of the field being resolved
|
* Parent type of the field being resolved.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var ObjectType
|
* @var ObjectType
|
||||||
@ -52,7 +53,7 @@ class ResolveInfo
|
|||||||
public $parentType;
|
public $parentType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to this field from the very root value
|
* Path to this field from the very root value.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var string[][]
|
* @var string[][]
|
||||||
@ -60,7 +61,7 @@ class ResolveInfo
|
|||||||
public $path;
|
public $path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instance of a schema used for execution
|
* Instance of a schema used for execution.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var Schema
|
* @var Schema
|
||||||
@ -68,7 +69,7 @@ class ResolveInfo
|
|||||||
public $schema;
|
public $schema;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AST of all fragments defined in query
|
* AST of all fragments defined in query.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var FragmentDefinitionNode[]
|
* @var FragmentDefinitionNode[]
|
||||||
@ -76,15 +77,15 @@ class ResolveInfo
|
|||||||
public $fragments = [];
|
public $fragments = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root value passed to query execution
|
* Root value passed to query execution.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var mixed|null
|
* @var mixed
|
||||||
*/
|
*/
|
||||||
public $rootValue;
|
public $rootValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AST of operation definition node (query, mutation)
|
* AST of operation definition node (query, mutation).
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var OperationDefinitionNode|null
|
* @var OperationDefinitionNode|null
|
||||||
@ -92,7 +93,7 @@ class ResolveInfo
|
|||||||
public $operation;
|
public $operation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of variables passed to query execution
|
* Array of variables passed to query execution.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
* @var mixed[]
|
* @var mixed[]
|
||||||
@ -136,7 +137,7 @@ class ResolveInfo
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method that returns names of all fields selected in query for
|
* Helper method that returns names of all fields selected in query for
|
||||||
* $this->fieldName up to $depth levels
|
* $this->fieldName up to $depth levels.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* query MyQuery{
|
* query MyQuery{
|
||||||
@ -177,7 +178,10 @@ class ResolveInfo
|
|||||||
|
|
||||||
/** @var FieldNode $fieldNode */
|
/** @var FieldNode $fieldNode */
|
||||||
foreach ($this->fieldNodes as $fieldNode) {
|
foreach ($this->fieldNodes as $fieldNode) {
|
||||||
$fields = array_merge_recursive($fields, $this->foldSelectionSet($fieldNode->selectionSet, $depth));
|
$fields = array_merge_recursive(
|
||||||
|
$fields,
|
||||||
|
$this->foldSelectionSet($fieldNode->selectionSet, $depth)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
|
@ -345,7 +345,9 @@ abstract class Type implements JsonSerializable
|
|||||||
*/
|
*/
|
||||||
public static function getNullableType($type)
|
public static function getNullableType($type)
|
||||||
{
|
{
|
||||||
return $type instanceof NonNull ? $type->getWrappedType() : $type;
|
return $type instanceof NonNull
|
||||||
|
? $type->getWrappedType()
|
||||||
|
: $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -488,7 +488,9 @@ EOD;
|
|||||||
'type' => [
|
'type' => [
|
||||||
'type' => Type::nonNull(self::_type()),
|
'type' => Type::nonNull(self::_type()),
|
||||||
'resolve' => static function ($value) {
|
'resolve' => static function ($value) {
|
||||||
return method_exists($value, 'getType') ? $value->getType() : $value->type;
|
return method_exists($value, 'getType')
|
||||||
|
? $value->getType()
|
||||||
|
: $value->type;
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'defaultValue' => [
|
'defaultValue' => [
|
||||||
|
@ -768,8 +768,9 @@ class SchemaValidationContext
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $union->astNode ?
|
return $union->astNode
|
||||||
$union->astNode->types : null;
|
? $union->astNode->types
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateEnumValues(EnumType $enumType)
|
private function validateEnumValues(EnumType $enumType)
|
||||||
@ -824,8 +825,9 @@ class SchemaValidationContext
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $enum->astNode ?
|
return $enum->astNode
|
||||||
$enum->astNode->values : null;
|
? $enum->astNode->values
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateInputFields(InputObjectType $inputObj)
|
private function validateInputFields(InputObjectType $inputObj)
|
||||||
|
@ -394,8 +394,8 @@ class ASTDefinitionBuilder
|
|||||||
function ($typeNode) {
|
function ($typeNode) {
|
||||||
return $this->buildType($typeNode);
|
return $this->buildType($typeNode);
|
||||||
}
|
}
|
||||||
) :
|
)
|
||||||
[],
|
: [],
|
||||||
'astNode' => $def,
|
'astNode' => $def,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ use function is_string;
|
|||||||
* Similar to PHP array, but allows any type of data to act as key (including arrays, objects, scalars)
|
* Similar to PHP array, but allows any type of data to act as key (including arrays, objects, scalars)
|
||||||
*
|
*
|
||||||
* Note: unfortunately when storing array as key - access and modification is O(N)
|
* Note: unfortunately when storing array as key - access and modification is O(N)
|
||||||
* (yet this should be really rare case and should be avoided when possible)
|
* (yet this should rarely be the case and should be avoided when possible)
|
||||||
*/
|
*/
|
||||||
class MixedStore implements ArrayAccess
|
class MixedStore implements ArrayAccess
|
||||||
{
|
{
|
||||||
|
@ -609,7 +609,9 @@ class SchemaExtender
|
|||||||
}
|
}
|
||||||
|
|
||||||
$schemaExtensionASTNodes = count($schemaExtensions) > 0
|
$schemaExtensionASTNodes = count($schemaExtensions) > 0
|
||||||
? ($schema->extensionASTNodes ? array_merge($schema->extensionASTNodes, $schemaExtensions) : $schemaExtensions)
|
? ($schema->extensionASTNodes
|
||||||
|
? array_merge($schema->extensionASTNodes, $schemaExtensions)
|
||||||
|
: $schemaExtensions)
|
||||||
: $schema->extensionASTNodes;
|
: $schema->extensionASTNodes;
|
||||||
|
|
||||||
$types = array_merge(
|
$types = array_merge(
|
||||||
|
@ -353,8 +353,8 @@ class SchemaPrinter
|
|||||||
private static function printObject(ObjectType $type, array $options) : string
|
private static function printObject(ObjectType $type, array $options) : string
|
||||||
{
|
{
|
||||||
$interfaces = $type->getInterfaces();
|
$interfaces = $type->getInterfaces();
|
||||||
$implementedInterfaces = ! empty($interfaces) ?
|
$implementedInterfaces = ! empty($interfaces)
|
||||||
' implements ' . implode(
|
? ' implements ' . implode(
|
||||||
' & ',
|
' & ',
|
||||||
array_map(
|
array_map(
|
||||||
static function ($i) {
|
static function ($i) {
|
||||||
@ -362,7 +362,8 @@ class SchemaPrinter
|
|||||||
},
|
},
|
||||||
$interfaces
|
$interfaces
|
||||||
)
|
)
|
||||||
) : '';
|
)
|
||||||
|
: '';
|
||||||
|
|
||||||
return self::printDescription($options, $type) .
|
return self::printDescription($options, $type) .
|
||||||
sprintf("type %s%s {\n%s\n}", $type->name, $implementedInterfaces, self::printFields($options, $type));
|
sprintf("type %s%s {\n%s\n}", $type->name, $implementedInterfaces, self::printFields($options, $type));
|
||||||
|
@ -302,10 +302,12 @@ class TypeInfo
|
|||||||
case $node instanceof InlineFragmentNode:
|
case $node instanceof InlineFragmentNode:
|
||||||
case $node instanceof FragmentDefinitionNode:
|
case $node instanceof FragmentDefinitionNode:
|
||||||
$typeConditionNode = $node->typeCondition;
|
$typeConditionNode = $node->typeCondition;
|
||||||
$outputType = $typeConditionNode ? self::typeFromAST(
|
$outputType = $typeConditionNode
|
||||||
|
? self::typeFromAST(
|
||||||
$schema,
|
$schema,
|
||||||
$typeConditionNode
|
$typeConditionNode
|
||||||
) : Type::getNamedType($this->getType());
|
)
|
||||||
|
: Type::getNamedType($this->getType());
|
||||||
$this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null;
|
$this->typeStack[] = Type::isOutputType($outputType) ? $outputType : null;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -19,12 +19,14 @@ class LoneSchemaDefinition extends ValidationRule
|
|||||||
public function getVisitor(ValidationContext $context)
|
public function getVisitor(ValidationContext $context)
|
||||||
{
|
{
|
||||||
$oldSchema = $context->getSchema();
|
$oldSchema = $context->getSchema();
|
||||||
$alreadyDefined = $oldSchema !== null ? (
|
$alreadyDefined = $oldSchema !== null
|
||||||
|
? (
|
||||||
$oldSchema->getAstNode() ||
|
$oldSchema->getAstNode() ||
|
||||||
$oldSchema->getQueryType() ||
|
$oldSchema->getQueryType() ||
|
||||||
$oldSchema->getMutationType() ||
|
$oldSchema->getMutationType() ||
|
||||||
$oldSchema->getSubscriptionType()
|
$oldSchema->getSubscriptionType()
|
||||||
) : false;
|
)
|
||||||
|
: false;
|
||||||
|
|
||||||
$schemaDefinitionsCount = 0;
|
$schemaDefinitionsCount = 0;
|
||||||
|
|
||||||
|
@ -473,24 +473,24 @@ class OverlappingFieldsCanBeMerged extends ValidationRule
|
|||||||
private function doTypesConflict(OutputType $type1, OutputType $type2)
|
private function doTypesConflict(OutputType $type1, OutputType $type2)
|
||||||
{
|
{
|
||||||
if ($type1 instanceof ListOfType) {
|
if ($type1 instanceof ListOfType) {
|
||||||
return $type2 instanceof ListOfType ?
|
return $type2 instanceof ListOfType
|
||||||
$this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType()) :
|
? $this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType())
|
||||||
true;
|
: true;
|
||||||
}
|
}
|
||||||
if ($type2 instanceof ListOfType) {
|
if ($type2 instanceof ListOfType) {
|
||||||
return $type1 instanceof ListOfType ?
|
return $type1 instanceof ListOfType
|
||||||
$this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType()) :
|
? $this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType())
|
||||||
true;
|
: true;
|
||||||
}
|
}
|
||||||
if ($type1 instanceof NonNull) {
|
if ($type1 instanceof NonNull) {
|
||||||
return $type2 instanceof NonNull ?
|
return $type2 instanceof NonNull
|
||||||
$this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType()) :
|
? $this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType())
|
||||||
true;
|
: true;
|
||||||
}
|
}
|
||||||
if ($type2 instanceof NonNull) {
|
if ($type2 instanceof NonNull) {
|
||||||
return $type1 instanceof NonNull ?
|
return $type1 instanceof NonNull
|
||||||
$this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType()) :
|
? $this->doTypesConflict($type1->getWrappedType(), $type2->getWrappedType())
|
||||||
true;
|
: true;
|
||||||
}
|
}
|
||||||
if (Type::isLeafType($type1) || Type::isLeafType($type2)) {
|
if (Type::isLeafType($type1) || Type::isLeafType($type2)) {
|
||||||
return $type1 !== $type2;
|
return $type1 !== $type2;
|
||||||
|
@ -66,13 +66,15 @@ class ProvidedRequiredArgumentsOnDirectives extends ValidationRule
|
|||||||
}
|
}
|
||||||
|
|
||||||
$requiredArgsMap[$def->name->value] = Utils::keyMap(
|
$requiredArgsMap[$def->name->value] = Utils::keyMap(
|
||||||
$arguments ? array_filter($arguments, static function (Node $argument) : bool {
|
$arguments
|
||||||
|
? array_filter($arguments, static function (Node $argument) : bool {
|
||||||
return $argument instanceof NonNullTypeNode &&
|
return $argument instanceof NonNullTypeNode &&
|
||||||
(
|
(
|
||||||
! isset($argument->defaultValue) ||
|
! isset($argument->defaultValue) ||
|
||||||
$argument->defaultValue === null
|
$argument->defaultValue === null
|
||||||
);
|
);
|
||||||
}) : [],
|
})
|
||||||
|
: [],
|
||||||
static function (NamedTypeNode $argument) : string {
|
static function (NamedTypeNode $argument) : string {
|
||||||
return $argument->name->value;
|
return $argument->name->value;
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,7 @@ class DeferredFieldsTest extends TestCase
|
|||||||
return [
|
return [
|
||||||
'sync' => [
|
'sync' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'resolve' => function ($rootValue, $a, $c, ResolveInfo $info) {
|
'resolve' => function ($rootValue, $args, $context, ResolveInfo $info) {
|
||||||
$this->paths[] = $info->path;
|
$this->paths[] = $info->path;
|
||||||
|
|
||||||
return 'sync';
|
return 'sync';
|
||||||
@ -409,7 +409,7 @@ class DeferredFieldsTest extends TestCase
|
|||||||
],
|
],
|
||||||
'deferred' => [
|
'deferred' => [
|
||||||
'type' => Type::string(),
|
'type' => Type::string(),
|
||||||
'resolve' => function ($rootValue, $a, $c, ResolveInfo $info) {
|
'resolve' => function ($rootValue, $args, $context, ResolveInfo $info) {
|
||||||
$this->paths[] = $info->path;
|
$this->paths[] = $info->path;
|
||||||
|
|
||||||
return new Deferred(function () use ($info) {
|
return new Deferred(function () use ($info) {
|
||||||
@ -421,7 +421,7 @@ class DeferredFieldsTest extends TestCase
|
|||||||
],
|
],
|
||||||
'nest' => [
|
'nest' => [
|
||||||
'type' => $complexType,
|
'type' => $complexType,
|
||||||
'resolve' => function ($rootValue, $a, $c, ResolveInfo $info) {
|
'resolve' => function ($rootValue, $args, $context, ResolveInfo $info) {
|
||||||
$this->paths[] = $info->path;
|
$this->paths[] = $info->path;
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
@ -429,7 +429,7 @@ class DeferredFieldsTest extends TestCase
|
|||||||
],
|
],
|
||||||
'deferredNest' => [
|
'deferredNest' => [
|
||||||
'type' => $complexType,
|
'type' => $complexType,
|
||||||
'resolve' => function ($rootValue, $a, $c, ResolveInfo $info) {
|
'resolve' => function ($rootValue, $args, $context, ResolveInfo $info) {
|
||||||
$this->paths[] = $info->path;
|
$this->paths[] = $info->path;
|
||||||
|
|
||||||
return new Deferred(function () use ($info) {
|
return new Deferred(function () use ($info) {
|
||||||
|
@ -70,7 +70,12 @@ class VisitorTest extends ValidatorTestCase
|
|||||||
/** @var Node $node */
|
/** @var Node $node */
|
||||||
[$node, $key, $parent, $path, $ancestors] = $args;
|
[$node, $key, $parent, $path, $ancestors] = $args;
|
||||||
|
|
||||||
$parentArray = $parent && ! is_array($parent) ? ($parent instanceof NodeList ? iterator_to_array($parent) : $parent->toArray()) : $parent;
|
$parentArray = $parent && ! is_array($parent)
|
||||||
|
? ($parent instanceof NodeList
|
||||||
|
? iterator_to_array($parent)
|
||||||
|
: $parent->toArray()
|
||||||
|
)
|
||||||
|
: $parent;
|
||||||
|
|
||||||
self::assertInstanceOf(Node::class, $node);
|
self::assertInstanceOf(Node::class, $node);
|
||||||
self::assertContains($node->kind, array_keys(NodeKind::$classMap));
|
self::assertContains($node->kind, array_keys(NodeKind::$classMap));
|
||||||
@ -114,7 +119,9 @@ class VisitorTest extends ValidatorTestCase
|
|||||||
{
|
{
|
||||||
$result = $ast;
|
$result = $ast;
|
||||||
foreach ($path as $key) {
|
foreach ($path as $key) {
|
||||||
$resultArray = $result instanceof NodeList ? iterator_to_array($result) : $result->toArray();
|
$resultArray = $result instanceof NodeList
|
||||||
|
? iterator_to_array($result)
|
||||||
|
: $result->toArray();
|
||||||
self::assertArrayHasKey($key, $resultArray);
|
self::assertArrayHasKey($key, $resultArray);
|
||||||
$result = $resultArray[$key];
|
$result = $resultArray[$key];
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,9 @@ class ScalarSerializationTest extends TestCase
|
|||||||
{
|
{
|
||||||
// Type System: Scalar coercion
|
// Type System: Scalar coercion
|
||||||
/**
|
/**
|
||||||
* @see it('serializes output int')
|
* @see it('serializes output as Int')
|
||||||
*/
|
*/
|
||||||
public function testSerializesOutputInt() : void
|
public function testSerializesOutputAsInt() : void
|
||||||
{
|
{
|
||||||
$intType = Type::int();
|
$intType = Type::int();
|
||||||
|
|
||||||
@ -114,9 +114,9 @@ class ScalarSerializationTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('serializes output float')
|
* @see it('serializes output as Float')
|
||||||
*/
|
*/
|
||||||
public function testSerializesOutputFloat() : void
|
public function testSerializesOutputAsFloat() : void
|
||||||
{
|
{
|
||||||
$floatType = Type::float();
|
$floatType = Type::float();
|
||||||
|
|
||||||
@ -149,9 +149,9 @@ class ScalarSerializationTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('serializes output strings')
|
* @see it('serializes output as String')
|
||||||
*/
|
*/
|
||||||
public function testSerializesOutputStrings() : void
|
public function testSerializesOutputAsString() : void
|
||||||
{
|
{
|
||||||
$stringType = Type::string();
|
$stringType = Type::string();
|
||||||
|
|
||||||
@ -181,23 +181,27 @@ class ScalarSerializationTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see it('serializes output boolean')
|
* @see it('serializes output as Boolean')
|
||||||
*/
|
*/
|
||||||
public function testSerializesOutputBoolean() : void
|
public function testSerializesOutputAsBoolean() : void
|
||||||
{
|
{
|
||||||
$boolType = Type::boolean();
|
$boolType = Type::boolean();
|
||||||
|
|
||||||
self::assertTrue($boolType->serialize('string'));
|
|
||||||
self::assertFalse($boolType->serialize(''));
|
|
||||||
self::assertTrue($boolType->serialize('1'));
|
|
||||||
self::assertTrue($boolType->serialize(1));
|
|
||||||
self::assertFalse($boolType->serialize(0));
|
|
||||||
self::assertTrue($boolType->serialize(true));
|
self::assertTrue($boolType->serialize(true));
|
||||||
|
self::assertTrue($boolType->serialize(1));
|
||||||
|
self::assertTrue($boolType->serialize('1'));
|
||||||
|
self::assertTrue($boolType->serialize('string'));
|
||||||
|
|
||||||
self::assertFalse($boolType->serialize(false));
|
self::assertFalse($boolType->serialize(false));
|
||||||
// TODO: how should it behave on '0'?
|
self::assertFalse($boolType->serialize(0));
|
||||||
|
self::assertFalse($boolType->serialize('0'));
|
||||||
|
self::assertFalse($boolType->serialize(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSerializesOutputID() : void
|
/**
|
||||||
|
* @see it('serializes output as ID')
|
||||||
|
*/
|
||||||
|
public function testSerializesOutputAsID() : void
|
||||||
{
|
{
|
||||||
$idType = Type::id();
|
$idType = Type::id();
|
||||||
|
|
||||||
|
@ -219,7 +219,9 @@ class SchemaExtenderTest extends TestCase
|
|||||||
{
|
{
|
||||||
$ast = Parser::parse(SchemaPrinter::doPrint($extendedSchema));
|
$ast = Parser::parse(SchemaPrinter::doPrint($extendedSchema));
|
||||||
$ast->definitions = array_values(array_filter(
|
$ast->definitions = array_values(array_filter(
|
||||||
$ast->definitions instanceof NodeList ? iterator_to_array($ast->definitions->getIterator()) : $ast->definitions,
|
$ast->definitions instanceof NodeList
|
||||||
|
? iterator_to_array($ast->definitions->getIterator())
|
||||||
|
: $ast->definitions,
|
||||||
function (Node $node) : bool {
|
function (Node $node) : bool {
|
||||||
return ! in_array(Printer::doPrint($node), $this->testSchemaDefinitions, true);
|
return ! in_array(Printer::doPrint($node), $this->testSchemaDefinitions, true);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,9 @@ function renderClassMethod(ReflectionMethod $method) {
|
|||||||
$def = $type . '$' . $p->getName();
|
$def = $type . '$' . $p->getName();
|
||||||
|
|
||||||
if ($p->isDefaultValueAvailable()) {
|
if ($p->isDefaultValueAvailable()) {
|
||||||
$val = $p->isDefaultValueConstant() ? $p->getDefaultValueConstantName() : $p->getDefaultValue();
|
$val = $p->isDefaultValueConstant()
|
||||||
|
? $p->getDefaultValueConstantName()
|
||||||
|
: $p->getDefaultValue();
|
||||||
$def .= " = " . Utils::printSafeJson($val);
|
$def .= " = " . Utils::printSafeJson($val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user