vendor/webonyx/graphql-php/src/Executor/Executor.php line 156

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace GraphQL\Executor;
  4. use ArrayAccess;
  5. use Closure;
  6. use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
  7. use GraphQL\Executor\Promise\Promise;
  8. use GraphQL\Executor\Promise\PromiseAdapter;
  9. use GraphQL\Language\AST\DocumentNode;
  10. use GraphQL\Type\Definition\ResolveInfo;
  11. use GraphQL\Type\Schema;
  12. use function is_array;
  13. use function is_object;
  14. /**
  15.  * Implements the "Evaluating requests" section of the GraphQL specification.
  16.  */
  17. class Executor
  18. {
  19.     /** @var callable */
  20.     private static $defaultFieldResolver = [self::class, 'defaultFieldResolver'];
  21.     /** @var PromiseAdapter */
  22.     private static $defaultPromiseAdapter;
  23.     /** @var callable */
  24.     private static $implementationFactory = [ReferenceExecutor::class, 'create'];
  25.     public static function getDefaultFieldResolver() : callable
  26.     {
  27.         return self::$defaultFieldResolver;
  28.     }
  29.     /**
  30.      * Set a custom default resolve function.
  31.      */
  32.     public static function setDefaultFieldResolver(callable $fieldResolver)
  33.     {
  34.         self::$defaultFieldResolver $fieldResolver;
  35.     }
  36.     public static function getPromiseAdapter() : PromiseAdapter
  37.     {
  38.         return self::$defaultPromiseAdapter ?? (self::$defaultPromiseAdapter = new SyncPromiseAdapter());
  39.     }
  40.     /**
  41.      * Set a custom default promise adapter.
  42.      */
  43.     public static function setPromiseAdapter(?PromiseAdapter $defaultPromiseAdapter null)
  44.     {
  45.         self::$defaultPromiseAdapter $defaultPromiseAdapter;
  46.     }
  47.     public static function getImplementationFactory() : callable
  48.     {
  49.         return self::$implementationFactory;
  50.     }
  51.     /**
  52.      * Set a custom executor implementation factory.
  53.      */
  54.     public static function setImplementationFactory(callable $implementationFactory)
  55.     {
  56.         self::$implementationFactory $implementationFactory;
  57.     }
  58.     /**
  59.      * Executes DocumentNode against given $schema.
  60.      *
  61.      * Always returns ExecutionResult and never throws.
  62.      * All errors which occur during operation execution are collected in `$result->errors`.
  63.      *
  64.      * @param mixed|null                    $rootValue
  65.      * @param mixed|null                    $contextValue
  66.      * @param array<mixed>|ArrayAccess|null $variableValues
  67.      * @param string|null                   $operationName
  68.      *
  69.      * @return ExecutionResult|Promise
  70.      *
  71.      * @api
  72.      */
  73.     public static function execute(
  74.         Schema $schema,
  75.         DocumentNode $documentNode,
  76.         $rootValue null,
  77.         $contextValue null,
  78.         $variableValues null,
  79.         $operationName null,
  80.         ?callable $fieldResolver null
  81.     ) {
  82.         // TODO: deprecate (just always use SyncAdapter here) and have `promiseToExecute()` for other cases
  83.         $promiseAdapter = static::getPromiseAdapter();
  84.         $result = static::promiseToExecute(
  85.             $promiseAdapter,
  86.             $schema,
  87.             $documentNode,
  88.             $rootValue,
  89.             $contextValue,
  90.             $variableValues,
  91.             $operationName,
  92.             $fieldResolver
  93.         );
  94.         if ($promiseAdapter instanceof SyncPromiseAdapter) {
  95.             $result $promiseAdapter->wait($result);
  96.         }
  97.         return $result;
  98.     }
  99.     /**
  100.      * Same as execute(), but requires promise adapter and returns a promise which is always
  101.      * fulfilled with an instance of ExecutionResult and never rejected.
  102.      *
  103.      * Useful for async PHP platforms.
  104.      *
  105.      * @param mixed|null        $rootValue
  106.      * @param mixed|null        $contextValue
  107.      * @param array<mixed>|null $variableValues
  108.      * @param string|null       $operationName
  109.      *
  110.      * @return Promise
  111.      *
  112.      * @api
  113.      */
  114.     public static function promiseToExecute(
  115.         PromiseAdapter $promiseAdapter,
  116.         Schema $schema,
  117.         DocumentNode $documentNode,
  118.         $rootValue null,
  119.         $contextValue null,
  120.         $variableValues null,
  121.         $operationName null,
  122.         ?callable $fieldResolver null
  123.     ) {
  124.         $factory self::$implementationFactory;
  125.         /** @var ExecutorImplementation $executor */
  126.         $executor $factory(
  127.             $promiseAdapter,
  128.             $schema,
  129.             $documentNode,
  130.             $rootValue,
  131.             $contextValue,
  132.             $variableValues,
  133.             $operationName,
  134.             $fieldResolver ?? self::$defaultFieldResolver
  135.         );
  136.         return $executor->doExecute();
  137.     }
  138.     /**
  139.      * If a resolve function is not given, then a default resolve behavior is used
  140.      * which takes the property of the root value of the same name as the field
  141.      * and returns it as the result, or if it's a function, returns the result
  142.      * of calling that function while passing along args and context.
  143.      *
  144.      * @param mixed                $objectValue
  145.      * @param array<string, mixed> $args
  146.      * @param mixed|null           $contextValue
  147.      *
  148.      * @return mixed|null
  149.      */
  150.     public static function defaultFieldResolver($objectValue$args$contextValueResolveInfo $info)
  151.     {
  152.         $fieldName $info->fieldName;
  153.         $property  null;
  154.         if (is_array($objectValue) || $objectValue instanceof ArrayAccess) {
  155.             if (isset($objectValue[$fieldName])) {
  156.                 $property $objectValue[$fieldName];
  157.             }
  158.         } elseif (is_object($objectValue)) {
  159.             if (isset($objectValue->{$fieldName})) {
  160.                 $property $objectValue->{$fieldName};
  161.             }
  162.         }
  163.         return $property instanceof Closure
  164.             $property($objectValue$args$contextValue$info)
  165.             : $property;
  166.     }
  167. }