LocalFileClient.php 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the league/commonmark package.
  5. *
  6. * (c) Colin O'Dell <colinodell@gmail.com>
  7. *
  8. * Adapted from the embed/embed test suite,
  9. * (c) 2017 Oscar Otero Marzoa, used under the MIT license.
  10. *
  11. * For the full copyright and license information, please view the LICENSE
  12. * file that was distributed with this source code.
  13. */
  14. namespace League\CommonMark\Tests\Functional\Extension\Embed\Bridge;
  15. use Embed\Http\CurlClient;
  16. use Embed\Http\FactoryDiscovery;
  17. use League\CommonMark\Exception\IOException;
  18. use Psr\Http\Client\ClientInterface;
  19. use Psr\Http\Message\RequestInterface;
  20. use Psr\Http\Message\ResponseFactoryInterface;
  21. use Psr\Http\Message\ResponseInterface;
  22. use Psr\Http\Message\UriInterface;
  23. /**
  24. * Decorator to cache requests into files
  25. */
  26. final class LocalFileClient implements ClientInterface
  27. {
  28. private string $path;
  29. private ResponseFactoryInterface $responseFactory;
  30. private ClientInterface $client;
  31. public function __construct(string $path)
  32. {
  33. $this->path = $path;
  34. $this->responseFactory = FactoryDiscovery::getResponseFactory();
  35. $this->client = new CurlClient($this->responseFactory);
  36. }
  37. public function sendRequest(RequestInterface $request): ResponseInterface
  38. {
  39. $uri = $request->getUri();
  40. $filename = $this->path . '/' . self::getFilename($uri);
  41. if (\is_file($filename)) {
  42. $response = $this->readResponse($filename);
  43. } else {
  44. $response = $this->client->sendRequest($request);
  45. $this->saveResponse($response, $filename);
  46. }
  47. return $response;
  48. }
  49. public static function getFilename(UriInterface $uri): string
  50. {
  51. $query = $uri->getQuery();
  52. return \sprintf(
  53. '%s.%s%s.json',
  54. $uri->getHost(),
  55. \trim(\preg_replace('/[^\w.-]+/', '-', \strtolower($uri->getPath())) ?? '', '-'),
  56. $query ? '.' . \md5($uri->getQuery()) : ''
  57. );
  58. }
  59. private function readResponse(string $filename): ResponseInterface
  60. {
  61. $file = \file_get_contents($filename);
  62. if ($file === false) {
  63. throw new IOException(\sprintf('Unable to read file "%s"', $filename));
  64. }
  65. $message = \json_decode($file, true, JSON_THROW_ON_ERROR);
  66. $response = $this->responseFactory->createResponse($message['statusCode'], $message['reasonPhrase']);
  67. foreach ($message['headers'] as $name => $value) {
  68. $response = $response->withHeader($name, $value);
  69. }
  70. $body = $response->getBody();
  71. $body->write($message['body']);
  72. $body->rewind();
  73. return $response;
  74. }
  75. private function saveResponse(ResponseInterface $response, string $filename): void
  76. {
  77. $message = [
  78. 'headers' => $response->getHeaders(),
  79. 'statusCode' => $response->getStatusCode(),
  80. 'reasonPhrase' => $response->getReasonPhrase(),
  81. 'body' => (string) $response->getBody(),
  82. ];
  83. \file_put_contents($filename, \json_encode($message, JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
  84. }
  85. }