1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Http\Client\Plugin\Vcr\Recorder; |
6
|
|
|
|
7
|
|
|
use GuzzleHttp\Psr7; |
8
|
|
|
use Psr\Http\Message\ResponseInterface; |
9
|
|
|
use Psr\Log\LoggerAwareInterface; |
10
|
|
|
use Psr\Log\LoggerAwareTrait; |
11
|
|
|
use Psr\Log\NullLogger; |
12
|
|
|
use Symfony\Component\Filesystem\Exception\IOException; |
13
|
|
|
use Symfony\Component\Filesystem\Filesystem; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* Stores responses using the `guzzlehttp/psr7` library to serialize and deserialize the response. |
17
|
|
|
* Target directory should be part of your VCS. |
18
|
|
|
* |
19
|
|
|
* @author Gary PEGEOT <[email protected]> |
20
|
|
|
*/ |
21
|
|
|
final class FilesystemRecorder implements RecorderInterface, PlayerInterface, LoggerAwareInterface |
22
|
|
|
{ |
23
|
|
|
use LoggerAwareTrait; |
24
|
|
|
|
25
|
|
|
/** |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
private $directory; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @var Filesystem |
32
|
|
|
*/ |
33
|
|
|
private $filesystem; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var array<string, string> |
37
|
|
|
*/ |
38
|
|
|
private $filters; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @param array<string, string> $filters |
42
|
|
|
*/ |
43
|
3 |
|
public function __construct(string $directory, ?Filesystem $filesystem = null, array $filters = []) |
44
|
|
|
{ |
45
|
3 |
|
$this->filesystem = $filesystem ?? new Filesystem(); |
46
|
|
|
|
47
|
3 |
|
if (!$this->filesystem->exists($directory)) { |
48
|
|
|
try { |
49
|
|
|
$this->filesystem->mkdir($directory); |
50
|
|
|
} catch (IOException $e) { |
51
|
|
|
throw new \InvalidArgumentException("Unable to create directory \"$directory\"/: {$e->getMessage()}", $e->getCode(), $e); |
52
|
|
|
} |
53
|
|
|
} |
54
|
|
|
|
55
|
3 |
|
$this->directory = realpath($directory).\DIRECTORY_SEPARATOR; |
56
|
3 |
|
$this->filters = $filters; |
57
|
3 |
|
$this->logger = new NullLogger(); |
58
|
3 |
|
} |
59
|
|
|
|
60
|
3 |
|
public function replay(string $name): ?ResponseInterface |
61
|
|
|
{ |
62
|
3 |
|
$filename = "{$this->directory}$name.txt"; |
63
|
3 |
|
$context = compact('filename'); |
64
|
|
|
|
65
|
3 |
|
if (!$this->filesystem->exists($filename)) { |
66
|
1 |
|
$this->log('Unable to replay {filename}', $context); |
67
|
|
|
|
68
|
1 |
|
return null; |
69
|
|
|
} |
70
|
|
|
|
71
|
2 |
|
$this->log('Response replayed from {filename}', $context); |
72
|
|
|
|
73
|
2 |
|
if (false === $content = file_get_contents($filename)) { |
74
|
|
|
throw new \RuntimeException(sprintf('Unable to read "%s" file content', $filename)); |
75
|
|
|
} |
76
|
|
|
|
77
|
2 |
|
return Psr7\parse_response($content); |
|
|
|
|
78
|
|
|
} |
79
|
|
|
|
80
|
2 |
|
public function record(string $name, ResponseInterface $response): void |
81
|
|
|
{ |
82
|
2 |
|
$filename = "{$this->directory}$name.txt"; |
83
|
2 |
|
$context = compact('name', 'filename'); |
84
|
|
|
|
85
|
2 |
|
if (null === $content = preg_replace(array_keys($this->filters), array_values($this->filters), Psr7\str($response))) { |
|
|
|
|
86
|
|
|
throw new \RuntimeException('Some of the provided response filters are invalid.'); |
87
|
|
|
} |
88
|
|
|
|
89
|
2 |
|
$this->filesystem->dumpFile($filename, $content); |
90
|
|
|
|
91
|
2 |
|
$this->log('Response for {name} stored into {filename}', $context); |
92
|
2 |
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @param array<string, string> $context |
96
|
|
|
*/ |
97
|
3 |
|
private function log(string $message, array $context = []): void |
98
|
|
|
{ |
99
|
3 |
|
$this->logger->debug("[VCR-PLUGIN][FilesystemRecorder] $message", $context); |
100
|
3 |
|
} |
101
|
|
|
} |
102
|
|
|
|
This function has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.