vendor/webonyx/graphql-php/src/GraphQL.php line 135

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace GraphQL;
  4. use GraphQL\Error\Error;
  5. use GraphQL\Executor\ExecutionResult;
  6. use GraphQL\Executor\Executor;
  7. use GraphQL\Executor\Promise\Adapter\SyncPromiseAdapter;
  8. use GraphQL\Executor\Promise\Promise;
  9. use GraphQL\Executor\Promise\PromiseAdapter;
  10. use GraphQL\Executor\ReferenceExecutor;
  11. use GraphQL\Experimental\Executor\CoroutineExecutor;
  12. use GraphQL\Language\AST\DocumentNode;
  13. use GraphQL\Language\Parser;
  14. use GraphQL\Language\Source;
  15. use GraphQL\Type\Definition\Directive;
  16. use GraphQL\Type\Definition\ScalarType;
  17. use GraphQL\Type\Definition\Type;
  18. use GraphQL\Type\Schema as SchemaType;
  19. use GraphQL\Validator\DocumentValidator;
  20. use GraphQL\Validator\Rules\QueryComplexity;
  21. use GraphQL\Validator\Rules\ValidationRule;
  22. use function array_values;
  23. use function count;
  24. use function trigger_error;
  25. use const E_USER_DEPRECATED;
  26. /**
  27.  * This is the primary facade for fulfilling GraphQL operations.
  28.  * See [related documentation](executing-queries.md).
  29.  */
  30. class GraphQL
  31. {
  32.     /**
  33.      * Executes graphql query.
  34.      *
  35.      * More sophisticated GraphQL servers, such as those which persist queries,
  36.      * may wish to separate the validation and execution phases to a static time
  37.      * tooling step, and a server runtime step.
  38.      *
  39.      * Available options:
  40.      *
  41.      * schema:
  42.      *    The GraphQL type system to use when validating and executing a query.
  43.      * source:
  44.      *    A GraphQL language formatted string representing the requested operation.
  45.      * rootValue:
  46.      *    The value provided as the first argument to resolver functions on the top
  47.      *    level type (e.g. the query object type).
  48.      * contextValue:
  49.      *    The context value is provided as an argument to resolver functions after
  50.      *    field arguments. It is used to pass shared information useful at any point
  51.      *    during executing this query, for example the currently logged in user and
  52.      *    connections to databases or other services.
  53.      * variableValues:
  54.      *    A mapping of variable name to runtime value to use for all variables
  55.      *    defined in the requestString.
  56.      * operationName:
  57.      *    The name of the operation to use if requestString contains multiple
  58.      *    possible operations. Can be omitted if requestString contains only
  59.      *    one operation.
  60.      * fieldResolver:
  61.      *    A resolver function to use when one is not provided by the schema.
  62.      *    If not provided, the default field resolver is used (which looks for a
  63.      *    value on the source value with the field's name).
  64.      * validationRules:
  65.      *    A set of rules for query validation step. Default value is all available rules.
  66.      *    Empty array would allow to skip query validation (may be convenient for persisted
  67.      *    queries which are validated before persisting and assumed valid during execution)
  68.      *
  69.      * @param string|DocumentNode $source
  70.      * @param mixed               $rootValue
  71.      * @param mixed               $contextValue
  72.      * @param mixed[]|null        $variableValues
  73.      * @param ValidationRule[]    $validationRules
  74.      *
  75.      * @api
  76.      */
  77.     public static function executeQuery(
  78.         SchemaType $schema,
  79.         $source,
  80.         $rootValue null,
  81.         $contextValue null,
  82.         $variableValues null,
  83.         ?string $operationName null,
  84.         ?callable $fieldResolver null,
  85.         ?array $validationRules null
  86.     ) : ExecutionResult {
  87.         $promiseAdapter = new SyncPromiseAdapter();
  88.         $promise self::promiseToExecute(
  89.             $promiseAdapter,
  90.             $schema,
  91.             $source,
  92.             $rootValue,
  93.             $contextValue,
  94.             $variableValues,
  95.             $operationName,
  96.             $fieldResolver,
  97.             $validationRules
  98.         );
  99.         return $promiseAdapter->wait($promise);
  100.     }
  101.     /**
  102.      * Same as executeQuery(), but requires PromiseAdapter and always returns a Promise.
  103.      * Useful for Async PHP platforms.
  104.      *
  105.      * @param string|DocumentNode   $source
  106.      * @param mixed                 $rootValue
  107.      * @param mixed                 $context
  108.      * @param mixed[]|null          $variableValues
  109.      * @param ValidationRule[]|null $validationRules
  110.      *
  111.      * @api
  112.      */
  113.     public static function promiseToExecute(
  114.         PromiseAdapter $promiseAdapter,
  115.         SchemaType $schema,
  116.         $source,
  117.         $rootValue null,
  118.         $context null,
  119.         $variableValues null,
  120.         ?string $operationName null,
  121.         ?callable $fieldResolver null,
  122.         ?array $validationRules null
  123.     ) : Promise {
  124.         try {
  125.             if ($source instanceof DocumentNode) {
  126.                 $documentNode $source;
  127.             } else {
  128.                 $documentNode Parser::parse(new Source($source ?? '''GraphQL'));
  129.             }
  130.             // FIXME
  131.             if (count($validationRules ?? []) === 0) {
  132.                 /** @var QueryComplexity $queryComplexity */
  133.                 $queryComplexity DocumentValidator::getRule(QueryComplexity::class);
  134.                 $queryComplexity->setRawVariableValues($variableValues);
  135.             } else {
  136.                 foreach ($validationRules as $rule) {
  137.                     if (! ($rule instanceof QueryComplexity)) {
  138.                         continue;
  139.                     }
  140.                     $rule->setRawVariableValues($variableValues);
  141.                 }
  142.             }
  143.             $validationErrors DocumentValidator::validate($schema$documentNode$validationRules);
  144.             if (count($validationErrors) > 0) {
  145.                 return $promiseAdapter->createFulfilled(
  146.                     new ExecutionResult(null$validationErrors)
  147.                 );
  148.             }
  149.             return Executor::promiseToExecute(
  150.                 $promiseAdapter,
  151.                 $schema,
  152.                 $documentNode,
  153.                 $rootValue,
  154.                 $context,
  155.                 $variableValues,
  156.                 $operationName,
  157.                 $fieldResolver
  158.             );
  159.         } catch (Error $e) {
  160.             return $promiseAdapter->createFulfilled(
  161.                 new ExecutionResult(null, [$e])
  162.             );
  163.         }
  164.     }
  165.     /**
  166.      * @deprecated Use executeQuery()->toArray() instead
  167.      *
  168.      * @param string|DocumentNode $source
  169.      * @param mixed               $rootValue
  170.      * @param mixed               $contextValue
  171.      * @param mixed[]|null        $variableValues
  172.      *
  173.      * @return Promise|mixed[]
  174.      *
  175.      * @codeCoverageIgnore
  176.      */
  177.     public static function execute(
  178.         SchemaType $schema,
  179.         $source,
  180.         $rootValue null,
  181.         $contextValue null,
  182.         $variableValues null,
  183.         ?string $operationName null
  184.     ) {
  185.         trigger_error(
  186.             __METHOD__ ' is deprecated, use GraphQL::executeQuery()->toArray() as a quick replacement',
  187.             E_USER_DEPRECATED
  188.         );
  189.         $promiseAdapter Executor::getPromiseAdapter();
  190.         $result         self::promiseToExecute(
  191.             $promiseAdapter,
  192.             $schema,
  193.             $source,
  194.             $rootValue,
  195.             $contextValue,
  196.             $variableValues,
  197.             $operationName
  198.         );
  199.         if ($promiseAdapter instanceof SyncPromiseAdapter) {
  200.             $result $promiseAdapter->wait($result)->toArray();
  201.         } else {
  202.             $result $result->then(static function (ExecutionResult $r) : array {
  203.                 return $r->toArray();
  204.             });
  205.         }
  206.         return $result;
  207.     }
  208.     /**
  209.      * @deprecated renamed to executeQuery()
  210.      *
  211.      * @param string|DocumentNode $source
  212.      * @param mixed               $rootValue
  213.      * @param mixed               $contextValue
  214.      * @param mixed[]|null        $variableValues
  215.      *
  216.      * @return ExecutionResult|Promise
  217.      *
  218.      * @codeCoverageIgnore
  219.      */
  220.     public static function executeAndReturnResult(
  221.         SchemaType $schema,
  222.         $source,
  223.         $rootValue null,
  224.         $contextValue null,
  225.         $variableValues null,
  226.         ?string $operationName null
  227.     ) {
  228.         trigger_error(
  229.             __METHOD__ ' is deprecated, use GraphQL::executeQuery() as a quick replacement',
  230.             E_USER_DEPRECATED
  231.         );
  232.         $promiseAdapter Executor::getPromiseAdapter();
  233.         $result         self::promiseToExecute(
  234.             $promiseAdapter,
  235.             $schema,
  236.             $source,
  237.             $rootValue,
  238.             $contextValue,
  239.             $variableValues,
  240.             $operationName
  241.         );
  242.         if ($promiseAdapter instanceof SyncPromiseAdapter) {
  243.             $result $promiseAdapter->wait($result);
  244.         }
  245.         return $result;
  246.     }
  247.     /**
  248.      * Returns directives defined in GraphQL spec
  249.      *
  250.      * @return Directive[]
  251.      *
  252.      * @api
  253.      */
  254.     public static function getStandardDirectives() : array
  255.     {
  256.         return array_values(Directive::getInternalDirectives());
  257.     }
  258.     /**
  259.      * Returns types defined in GraphQL spec
  260.      *
  261.      * @return Type[]
  262.      *
  263.      * @api
  264.      */
  265.     public static function getStandardTypes() : array
  266.     {
  267.         return array_values(Type::getStandardTypes());
  268.     }
  269.     /**
  270.      * Replaces standard types with types from this list (matching by name)
  271.      * Standard types not listed here remain untouched.
  272.      *
  273.      * @param array<string, ScalarType> $types
  274.      *
  275.      * @api
  276.      */
  277.     public static function overrideStandardTypes(array $types)
  278.     {
  279.         Type::overrideStandardTypes($types);
  280.     }
  281.     /**
  282.      * Returns standard validation rules implementing GraphQL spec
  283.      *
  284.      * @return ValidationRule[]
  285.      *
  286.      * @api
  287.      */
  288.     public static function getStandardValidationRules() : array
  289.     {
  290.         return array_values(DocumentValidator::defaultRules());
  291.     }
  292.     /**
  293.      * Set default resolver implementation
  294.      *
  295.      * @api
  296.      */
  297.     public static function setDefaultFieldResolver(callable $fn) : void
  298.     {
  299.         Executor::setDefaultFieldResolver($fn);
  300.     }
  301.     public static function setPromiseAdapter(?PromiseAdapter $promiseAdapter null) : void
  302.     {
  303.         Executor::setPromiseAdapter($promiseAdapter);
  304.     }
  305.     /**
  306.      * Experimental: Switch to the new executor
  307.      */
  308.     public static function useExperimentalExecutor()
  309.     {
  310.         trigger_error(
  311.             'Experimental Executor is deprecated and will be removed in the next major version',
  312.             E_USER_DEPRECATED
  313.         );
  314.         Executor::setImplementationFactory([CoroutineExecutor::class, 'create']);
  315.     }
  316.     /**
  317.      * Experimental: Switch back to the default executor
  318.      */
  319.     public static function useReferenceExecutor()
  320.     {
  321.         Executor::setImplementationFactory([ReferenceExecutor::class, 'create']);
  322.     }
  323.     /**
  324.      * Returns directives defined in GraphQL spec
  325.      *
  326.      * @deprecated Renamed to getStandardDirectives
  327.      *
  328.      * @return Directive[]
  329.      *
  330.      * @codeCoverageIgnore
  331.      */
  332.     public static function getInternalDirectives() : array
  333.     {
  334.         return self::getStandardDirectives();
  335.     }
  336. }