<commit_before><?php


namespace SilverStripe\GraphQL\QueryHandler;

use GraphQL\Error\Error;
use GraphQL\Error\SyntaxError;
use GraphQL\Executor\ExecutionResult;
use GraphQL\GraphQL;
use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\Parser;
use GraphQL\Language\Source;
use GraphQL\Language\SourceLocation;
use GraphQL\Type\Schema as GraphQLSchema;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\GraphQL\Middleware\QueryMiddleware;
use SilverStripe\GraphQL\Permission\MemberAware;
use SilverStripe\GraphQL\PersistedQuery\PersistedQueryMappingProvider;
use SilverStripe\GraphQL\PersistedQuery\PersistedQueryProvider;
use SilverStripe\GraphQL\Schema\Interfaces\ContextProvider;
use SilverStripe\GraphQL\Schema\Schema;
use SilverStripe\ORM\ValidationException;

/**
 * This class is responsible for taking query information from a controller,
 * processing it through middlewares, extracting the results from the GraphQL schema,
 * and formatting it into a suitable JSON response.
 */
class QueryHandler implements
    QueryHandlerInterface,
    PersistedQueryProvider
{
    use Extensible;
    use Injectable;
    use Configurable;
    use MemberAware;

    /**
     * @var ContextProvider[]
     */
    private array $contextProviders = [];

    private array $errorFormatter = [self::class, 'formatError'];

    /**
     * @config
     * @var callable|null
     */
    private $errorHandler = null;

    /**
     * @var QueryMiddleware[]
     */
    private array $middlewares = [];

    /**
     * QueryHandler constructor.
     * @param ContextProvider[] $contextProviders
     */
    public function __construct(array $contextProviders = [])
    {
        foreach ($contextProviders as $contextProvider) {
            $this->addContextProvider($contextProvider);
        }
    }

    /**
     * @param GraphQLSchema $schema
     * @param string|DocumentNode $query
     * @param array|null $vars
     * @return array
     */
    public function query(GraphQLSchema $schema, $query, ?array $vars = []): array
    {
        $executionResult = $this->queryAndReturnResult($schema, $query, $vars);

        // Already in array form
        if (is_array($executionResult)) {
            return $executionResult;
        }
        return $this->serialiseResult($executionResult);
    }

    /**
     * @param GraphQLSchema $schema
     * @param string|DocumentNode $query
     * @param array|null $vars
     * @return array|ExecutionResult
     */
    public function queryAndReturnResult(GraphQLSchema $schema, $query, ?array $vars = [])
    {
        if ($this->errorHandler) {
            set_error_handler($this->errorHandler);
        }
        $context = $this->getContext();
        $last = function ($schema, $query, $context, $vars) {
            return GraphQL::executeQuery($schema, $query, null, $context, $vars);
        };

        return $this->callMiddleware($schema, $query, $context, $vars, $last);
    }


    /**
     * get query from persisted id, return null if not found
     *
     * @param string $id
     * @return string|null
     */
    public function getQueryFromPersistedID(string $id): ?string
    {
        /** @var PersistedQueryMappingProvider $provider */
        $provider = Injector::inst()->get(PersistedQueryMappingProvider::class);<commit_msg>typecast vars to ensure the value is an array<commit_after><?php


namespace SilverStripe\GraphQL\QueryHandler;

use GraphQL\Error\Error;
use GraphQL\Error\SyntaxError;
use GraphQL\Executor\ExecutionResult;
use GraphQL\GraphQL;
use GraphQL\Language\AST\DocumentNode;
use GraphQL\Language\AST\NodeKind;
use GraphQL\Language\Parser;
use GraphQL\Language\Source;
use GraphQL\Language\SourceLocation;
use GraphQL\Type\Schema as GraphQLSchema;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\GraphQL\Middleware\QueryMiddleware;
use SilverStripe\GraphQL\Permission\MemberAware;
use SilverStripe\GraphQL\PersistedQuery\PersistedQueryMappingProvider;
use SilverStripe\GraphQL\PersistedQuery\PersistedQueryProvider;
use SilverStripe\GraphQL\Schema\Interfaces\ContextProvider;
use SilverStripe\GraphQL\Schema\Schema;
use SilverStripe\ORM\ValidationException;

/**
 * This class is responsible for taking query information from a controller,
 * processing it through middlewares, extracting the results from the GraphQL schema,
 * and formatting it into a suitable JSON response.
 */
class QueryHandler implements
    QueryHandlerInterface,
    PersistedQueryProvider
{
    use Extensible;
    use Injectable;
    use Configurable;
    use MemberAware;

    /**
     * @var ContextProvider[]
     */
    private array $contextProviders = [];

    private array $errorFormatter = [self::class, 'formatError'];

    /**
     * @config
     * @var callable|null
     */
    private $errorHandler = null;

    /**
     * @var QueryMiddleware[]
     */
    private array $middlewares = [];

    /**
     * QueryHandler constructor.
     * @param ContextProvider[] $contextProviders
     */
    public function __construct(array $contextProviders = [])
    {
        foreach ($contextProviders as $contextProvider) {
            $this->addContextProvider($contextProvider);
        }
    }

    /**
     * @param GraphQLSchema $schema
     * @param string|DocumentNode $query
     * @param array|null $vars
     * @return array
     */
    public function query(GraphQLSchema $schema, $query, ?array $vars = []): array
    {
        $executionResult = $this->queryAndReturnResult($schema, $query, $vars);

        // Already in array form
        if (is_array($executionResult)) {
            return $executionResult;
        }
        return $this->serialiseResult($executionResult);
    }

    /**
     * @param GraphQLSchema $schema
     * @param string|DocumentNode $query
     * @param array|null $vars
     * @return array|ExecutionResult
     */
    public function queryAndReturnResult(GraphQLSchema $schema, $query, ?array $vars = [])
    {
        if ($this->errorHandler) {
            set_error_handler($this->errorHandler);
        }
        $context = $this->getContext();
        $last = function ($schema, $query, $context, $vars) {
            return GraphQL::executeQuery($schema, $query, null, $context, $vars);
        };

        return $this->callMiddleware($schema, $query, $context, (array) $vars, $last);
    }


    /**
     * get query from persisted id, return null if not found
     *
     * @param string $id
     * @return string|null
     */
    public function getQueryFromPersistedID(string $id): ?string
    {
        /** @var PersistedQueryMappingProvider $provider */
        $provider = Injector::inst()->get(PersistedQueryMappingProvider::class);
{'fraction_non_alphanumeric': 0.1098775974950185, 'fraction_numerical': 0.0, 'mean_word_length': 3.321648216482165, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '344416', 'n_tokens_mistral': 2013, 'n_tokens_neox': 1986, 'n_words': 460}