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

QueryProcessor::processQuery()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

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