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

SubRequestBuffer::createRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 0
loc 23
rs 9.552
c 0
b 0
f 0
1
<?php
2
3
namespace Drupal\graphql\GraphQL\Buffers;
4
5
use Drupal\Core\Cache\CacheableDependencyInterface;
6
use Drupal\Core\Url;
7
use Drupal\graphql\GraphQL\Cache\CacheableValue;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\RequestStack;
10
use Symfony\Component\HttpKernel\HttpKernelInterface;
11
12
class SubRequestBuffer extends BufferBase {
13
14
  /**
15
   * The http kernel service.
16
   *
17
   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
18
   */
19
  protected $httpKernel;
20
21
  /**
22
   * The request stack service.
23
   *
24
   * @var \Symfony\Component\HttpFoundation\RequestStack
25
   */
26
  protected $requestStack;
27
28
  /**
29
   * SubrequestBuffer constructor.
30
   *
31
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $httpKernel
32
   *   The http kernel service.
33
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
34
   *   The request stack service.
35
   */
36
  public function __construct(HttpKernelInterface $httpKernel, RequestStack $requestStack) {
37
    $this->httpKernel = $httpKernel;
38
    $this->requestStack = $requestStack;
39
  }
40
41
  /**
42
   * Add an item to the buffer.
43
   *
44
   * @param \Drupal\Core\Url $url
45
   *   The url object to run the subrequest on.
46
   * @param callable $extract
47
   *   The callback to run within the sub-request.
48
   *
49
   * @return \Closure
50
   *   The callback to invoke to load the result for this buffer item.
51
   */
52
  public function add(Url $url, callable $extract) {
53
    $item = new \ArrayObject([
54
      'url' => $url,
55
      'extract' => $extract,
56
    ]);
57
58
    return $this->createBufferResolver($item);
59
  }
60
61
  /**
62
   * {@inheritdoc}
63
   */
64
  protected function getBufferId($item) {
65
    /** @var \Drupal\Core\GeneratedUrl $url */
66
    $url = $item['url']->toString(TRUE);
67
68
    return hash('sha256', json_encode([
69
      'url' => $url->getGeneratedUrl(),
70
      'tags' => $url->getCacheTags(),
71
      'contexts' => $url->getCacheContexts(),
72
      'age' => $url->getCacheMaxAge(),
73
    ]));
74
  }
75
  
76
  protected function createRequest(Request $current, array $buffer, $url) {
77
    $request = Request::create(
78
      $url,
79
      'GET',
80
      $current->query->all(),
81
      $current->cookies->all(),
82
      $current->files->all(),
83
      $current->server->all()
84
    );
85
86
    $request->attributes->set('_graphql_subrequest', function () use ($buffer) {
87
      return array_map(function ($item) {
88
        return $item['extract']($item['url']);
89
      }, $buffer);
90
    });
91
92
    $request->setRequestFormat('_graphql_subrequest');
93
    if ($session = $current->getSession()) {
94
      $request->setSession($session);
95
    }
96
    
97
    return $request;
98
  }
99
100
  /**
101
   * {@inheritdoc}
102
   */
103
  public function resolveBufferArray(array $buffer) {
104
    /** @var \Drupal\Core\GeneratedUrl $url */
105
    $url = reset($buffer)['url']->toString(TRUE);
106
107
    $current = $this->requestStack->getCurrentRequest();
108
    $target = $url->getGeneratedUrl();
109
    $request = $this->createRequest($current, $buffer, $target);
110
    
111
    /** @var \Drupal\graphql\GraphQL\Buffers\SubRequestResponse $response */
112
    $response = $this->httpKernel->handle($request, HttpKernelInterface::SUB_REQUEST);
113
    while ($response instanceof RedirectResponse) {
0 ignored issues
show
Bug introduced by
The class Drupal\graphql\GraphQL\Buffers\RedirectResponse does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
114
      $target = $response->getTargetUrl();
115
      $request = $this->createRequest($current, $buffer, $target);
116
      $response = $this->httpKernel->handle($request, HttpKernelInterface::SUB_REQUEST);
117
    }
118
119
    // TODO:
120
    // Remove the request stack manipulation once the core issue described at
121
    // https://www.drupal.org/node/2613044 is resolved.
122
    while ($this->requestStack->getCurrentRequest() !== $current) {
123
      $this->requestStack->pop();
124
    }
125
126
    if ($url instanceof CacheableDependencyInterface) {
0 ignored issues
show
Bug introduced by
The class Drupal\Core\Cache\CacheableDependencyInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
127
      $response->addCacheableDependency($url);
128
    }
129
    
130
    return array_map(function ($value) use ($response) {
131
      return new CacheableValue($value, [$response]);
132
    }, $response->getResult());
133
  }
134
135
}
136