Completed
Pull Request — 8.x-3.x (#525)
by Philipp
02:08
created

QueryProcessor::processQuery()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 41
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 22
nc 2
nop 3
dl 0
loc 41
rs 8.5806
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql\GraphQL\Execution;
4
5
use Drupal\Core\Cache\CacheableDependencyInterface;
6
use Drupal\Core\Cache\CacheableMetadata;
7
use Drupal\Core\Render\RenderContext;
8
use Drupal\Core\Render\RendererInterface;
9
use Drupal\Core\Session\AccountProxyInterface;
10
use Drupal\graphql\GraphQL\Schema\SchemaLoader;
11
use Drupal\graphql\Plugin\GraphQL\SchemaPluginManager;
12
use Drupal\graphql\QueryProvider\QueryProviderInterface;
13
use GraphQL\Error\FormattedError;
14
use GraphQL\Error\UserError;
15
use GraphQL\GraphQL;
16
use GraphQL\Server\Helper;
17
use GraphQL\Server\OperationParams;
18
use GraphQL\Server\RequestError;
19
use GraphQL\Server\ServerConfig;
20
use GraphQL\Type\Definition\ResolveInfo;
21
22
class QueryProcessor {
23
24
  /**
25
   * The current user account.
26
   *
27
   * @var \Drupal\Core\Session\AccountProxyInterface
28
   */
29
  protected $currentUser;
30
31
  /**
32
   * The graphql container parameters.
33
   *
34
   * @var array
35
   */
36
  protected $parameters;
37
38
  /**
39
   * The schema plugin manager.
40
   *
41
   * @var \Drupal\graphql\Plugin\GraphQL\SchemaPluginManager
42
   */
43
  protected $pluginManager;
44
45
  /**
46
   * The server helper.
47
   *
48
   * @var \GraphQL\Server\Helper
49
   */
50
  protected $helper;
51
52
  /**
53
   * The query provider service.
54
   *
55
   * @var \Drupal\graphql\QueryProvider\QueryProviderInterface
56
   */
57
  protected $queryProvider;
58
59
  /**
60
   * The renderer service.
61
   *
62
   * @var \Drupal\Core\Render\RendererInterface
63
   */
64
  protected $renderer;
65
66
  /**
67
   * QueryProcessor constructor.
68
   *
69
   * @param \Drupal\Core\Render\RendererInterface $renderer
70
   *   The renderer service.
71
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
72
   *   The current user.
73
   * @param \Drupal\graphql\Plugin\GraphQL\SchemaPluginManager $pluginManager
74
   *   The schema plugin manager.
75
   * @param \Drupal\graphql\QueryProvider\QueryProviderInterface $queryProvider
76
   *   The query provider service.
77
   * @param array $parameters
78
   *   The graphql container parameters.
79
   */
80
  public function __construct(
81
    RendererInterface $renderer,
82
    AccountProxyInterface $currentUser,
83
    SchemaPluginManager $pluginManager,
84
    QueryProviderInterface $queryProvider,
85
    array $parameters
86
  ) {
87
    $this->renderer = $renderer;
88
    $this->currentUser = $currentUser;
89
    $this->pluginManager = $pluginManager;
90
    $this->queryProvider = $queryProvider;
91
    $this->parameters = $parameters;
92
    $this->helper = new Helper();
93
  }
94
95
  /**
96
   * Execute a GraphQL query.
97
   *
98
   * @param string $schema
99
   *   The name of the schema to execute.
100
   * @param \GraphQL\Server\OperationParams|\GraphQL\Server\OperationParams[] $operations
101
   *   The graphql operation(s) to execute.
102
   * @param mixed $context
103
   *   The context for the query.
104
   *
105
   * @return \Drupal\graphql\GraphQL\Execution\QueryResult
106
   *   The query result.
107
   */
108
  public function processQuery($schema, $operations, $context = NULL) {
109
    $debug = !empty($this->parameters['development']);
110
111
    // Load the plugin from the schema manager.
112
    $plugin = $this->pluginManager->createInstance($schema);
113
    $schema = $plugin->getSchema();
114
115
    // Create the server config.
116
    $server = ServerConfig::create();
117
    $server->setDebug($debug);
118
    $server->setSchema($schema);
119
    $server->setContext($context);
120
    $server->setQueryBatching(TRUE);
121
    $server->setPersistentQueryLoader(function ($id, OperationParams $operation) {
122
      if ($query = $this->queryProvider->getQuery($id, $operation)) {
123
        return $query;
124
      }
125
126
      throw new RequestError(sprintf("Failed to load query map for id '%s'.", $id));
127
    });
128
129
    // Evaluating the request can potentially invoke rendering. We allow those
130
    // to "leak" and collect them here in a render context.
131
    $context = new RenderContext();
132
    /** @var \GraphQL\Executor\ExecutionResult|\GraphQL\Executor\ExecutionResult[] $result */
133
    $result = $this->renderer->executeInRenderContext($context, function() use ($server, $operations) {
134
      if (is_array($operations)) {
135
        return $this->helper->executeBatch($server, $operations);
136
      }
137
138
      return $this->helper->executeOperation($server, $operations);
139
    });
140
141
    $metadata = new CacheableMetadata();
142
    // Apply render context cache metadata to the response.
143
    if (!$context->isEmpty()) {
144
      $metadata->addCacheableDependency($context->pop());
145
    }
146
147
    return new QueryResult($result, $metadata);
148
  }
149
150
}
151