Completed
Pull Request — 8.x-3.x (#716)
by Sebastian
01:51
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
use Symfony\Component\HttpFoundation\RedirectResponse;
12
13
class SubRequestBuffer extends BufferBase {
14
15
  /**
16
   * The http kernel service.
17
   *
18
   * @var \Symfony\Component\HttpKernel\HttpKernelInterface
19
   */
20
  protected $httpKernel;
21
22
  /**
23
   * The request stack service.
24
   *
25
   * @var \Symfony\Component\HttpFoundation\RequestStack
26
   */
27
  protected $requestStack;
28
29
  /**
30
   * SubrequestBuffer constructor.
31
   *
32
   * @param \Symfony\Component\HttpKernel\HttpKernelInterface $httpKernel
33
   *   The http kernel service.
34
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
35
   *   The request stack service.
36
   */
37
  public function __construct(HttpKernelInterface $httpKernel, RequestStack $requestStack) {
38
    $this->httpKernel = $httpKernel;
39
    $this->requestStack = $requestStack;
40
  }
41
42
  /**
43
   * Add an item to the buffer.
44
   *
45
   * @param \Drupal\Core\Url $url
46
   *   The url object to run the subrequest on.
47
   * @param callable $extract
48
   *   The callback to run within the sub-request.
49
   *
50
   * @return \Closure
51
   *   The callback to invoke to load the result for this buffer item.
52
   */
53
  public function add(Url $url, callable $extract) {
54
    $item = new \ArrayObject([
55
      'url' => $url,
56
      'extract' => $extract,
57
    ]);
58
59
    return $this->createBufferResolver($item);
60
  }
61
62
  /**
63
   * {@inheritdoc}
64
   */
65
  protected function getBufferId($item) {
66
    /** @var \Drupal\Core\GeneratedUrl $url */
67
    $url = $item['url']->toString(TRUE);
68
69
    return hash('sha256', json_encode([
70
      'url' => $url->getGeneratedUrl(),
71
      'tags' => $url->getCacheTags(),
72
      'contexts' => $url->getCacheContexts(),
73
      'age' => $url->getCacheMaxAge(),
74
    ]));
75
  }
76
  
77
  protected function createRequest(Request $current, array $buffer, $url) {
78
    $request = Request::create(
79
      $url,
80
      'GET',
81
      $current->query->all(),
82
      $current->cookies->all(),
83
      $current->files->all(),
84
      $current->server->all()
85
    );
86
87
    $request->attributes->set('_graphql_subrequest', function () use ($buffer) {
88
      return array_map(function ($item) {
89
        return $item['extract']($item['url']);
90
      }, $buffer);
91
    });
92
93
    $request->setRequestFormat('_graphql_subrequest');
94
    if ($session = $current->getSession()) {
95
      $request->setSession($session);
96
    }
97
    
98
    return $request;
99
  }
100
101
  /**
102
   * {@inheritdoc}
103
   */
104
  public function resolveBufferArray(array $buffer) {
105
    /** @var \Drupal\Core\GeneratedUrl $url */
106
    $url = reset($buffer)['url']->toString(TRUE);
107
108
    $current = $this->requestStack->getCurrentRequest();
109
    $target = $url->getGeneratedUrl();
110
    $request = $this->createRequest($current, $buffer, $target);
111
    
112
    /** @var \Drupal\graphql\GraphQL\Buffers\SubRequestResponse $response */
113
    $response = $this->httpKernel->handle($request, HttpKernelInterface::SUB_REQUEST);
114
    while ($response instanceof RedirectResponse) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\HttpFoundation\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...
115
      $target = $response->getTargetUrl();
116
      $request = $this->createRequest($current, $buffer, $target);
117
      $response = $this->httpKernel->handle($request, HttpKernelInterface::SUB_REQUEST);
118
    }
119
120
    // TODO:
121
    // Remove the request stack manipulation once the core issue described at
122
    // https://www.drupal.org/node/2613044 is resolved.
123
    while ($this->requestStack->getCurrentRequest() !== $current) {
124
      $this->requestStack->pop();
125
    }
126
127
    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...
128
      $response->addCacheableDependency($url);
129
    }
130
    
131
    return array_map(function ($value) use ($response) {
132
      return new CacheableValue($value, [$response]);
133
    }, $response->getResult());
134
  }
135
136
}
137