View source
<?php
namespace Drupal\graphql\GraphQL\Buffers;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Url;
use Drupal\Core\Routing\LocalRedirectResponse;
use Drupal\graphql\GraphQL\Buffers\SubRequestResponse;
use Drupal\graphql\GraphQL\Cache\CacheableValue;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class SubRequestBuffer extends BufferBase {
protected $httpKernel;
protected $requestStack;
public function __construct(HttpKernelInterface $httpKernel, RequestStack $requestStack) {
$this->httpKernel = $httpKernel;
$this->requestStack = $requestStack;
}
public function add(Url $url, callable $extract) {
$item = new \ArrayObject([
'url' => $url,
'extract' => $extract,
]);
return $this
->createBufferResolver($item);
}
protected function getBufferId($item) {
$url = $item['url']
->toString(TRUE);
return hash('sha256', json_encode([
'url' => $url
->getGeneratedUrl(),
'tags' => $url
->getCacheTags(),
'contexts' => $url
->getCacheContexts(),
'age' => $url
->getCacheMaxAge(),
]));
}
protected function createRequest(Request $current, array $buffer, $url) {
$request = Request::create($url, 'GET', $current->query
->all(), $current->cookies
->all(), $current->files
->all(), $current->server
->all());
$request->attributes
->set('_graphql_subrequest', function () use ($buffer) {
return array_map(function ($item) {
return $item['extract']($item['url']);
}, $buffer);
});
if ($session = $current
->getSession()) {
$request
->setSession($session);
}
return $request;
}
public function resolveBufferArray(array $buffer) {
$url = reset($buffer)['url']
->toString(TRUE);
$current = $this->requestStack
->getCurrentRequest();
$target = $url
->getGeneratedUrl();
$request = $this
->createRequest($current, $buffer, $target);
$response = $this->httpKernel
->handle($request, HttpKernelInterface::SUB_REQUEST);
while ($response instanceof LocalRedirectResponse) {
$target = $response
->getTargetUrl();
$request = $this
->createRequest($current, $buffer, $target);
$response = $this->httpKernel
->handle($request, HttpKernelInterface::SUB_REQUEST);
}
if (!$response instanceof SubRequestResponse) {
return array_fill_keys(array_keys($buffer), NULL);
}
while ($this->requestStack
->getCurrentRequest() !== $current) {
$this->requestStack
->pop();
}
if ($url instanceof CacheableDependencyInterface) {
$response
->addCacheableDependency($url);
}
return array_map(function ($value) use ($response) {
return new CacheableValue($value, [
$response,
]);
}, $response
->getResult());
}
}