Completed
Push — master ( a108e7...e09842 )
by Gareth
03:22
created

HttpPlayback   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 72.72%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
wmc 24
c 1
b 0
f 1
lcom 1
cbo 6
dl 0
loc 190
ccs 64
cts 88
cp 0.7272
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 17 3
A setPlaybackOptions() 0 19 4
C getHttpClient() 0 42 7
A setHttpClient() 0 6 1
A getRecordLocation() 0 12 2
A getRecordFilePath() 0 7 1
A getRecordings() 0 7 1
B endRecord() 0 42 5
1
<?php
2
3
namespace garethp\ews\HttpPlayback;
4
5
use GuzzleHttp\HandlerStack;
6
use GuzzleHttp\Middleware;
7
use GuzzleHttp\Handler\MockHandler;
8
use GuzzleHttp\Psr7\Request;
9
use GuzzleHttp\Psr7\Response;
10
use GuzzleHttp\Client;
11
12
class HttpPlayback
13
{
14
    protected $mode = 'live';
15
16
    protected $callList = [];
17
18
    protected $recordLocation;
19
20
    protected $recordFileName = 'saveState.json';
21
22
    private $shutdownRegistered = false;
23
24
    private static $instances = [];
25
26
    /**
27
     * @var Client
28
     */
29
    private $client;
30
31 31
    public static function getInstance($options = [])
32
    {
33 31
        foreach (self::$instances as $instance) {
34 30
            if ($instance['options'] == $options) {
35 31
                return $instance['instance'];
36
            }
37
        }
38
39 28
        $instance = new static();
40 28
        $instance->setPlaybackOptions($options);
41 28
        self::$instances[] = [
42 28
            'instance' => $instance,
43 28
            'options' => $options
44
        ];
45
46 28
        return $instance;
47
    }
48
49 29
    public function setPlaybackOptions($options = [])
50
    {
51 29
        $options = array_replace_recursive(
52 29
            ['mode' => null, 'recordLocation' => null, 'recordFileName' => null],
53
            $options
54
        );
55
56 29
        if ($options['mode'] !== null) {
57 28
            $this->mode = $options['mode'];
58
        }
59
60 29
        if ($options['recordLocation'] !== null) {
61 1
            $this->recordLocation = $options['recordLocation'];
62
        }
63
64 29
        if ($options['recordFileName'] !== null) {
65 28
            $this->recordFileName = $options['recordFileName'];
66
        }
67
    }
68
69
    /**
70
     * Get the client for making calls
71
     *
72
     * @return Client
73
     */
74 24
    public function getHttpClient()
75
    {
76 24
        if ($this->client == null) {
77 24
            $handler = HandlerStack::create();
78
79 24
            if ($this->mode == 'record') {
80
                $history = Middleware::history($this->callList);
81
                $handler->push($history);
82 24
            } elseif ($this->mode == 'playback') {
83 24
                $recordings = $this->getRecordings();
84
85 22
                $playList = $recordings;
86 22
                $mockedResponses = [];
87 22
                foreach ($playList as $item) {
88 22
                    if (!$item['error']) {
89 22
                        $mockedResponses[] = new Response($item['statusCode'], $item['headers'], $item['body']);
90
                    } else {
91
                        $errorClass = $item['errorClass'];
92
                        $request = new Request(
93
                            $item['request']['method'],
94
                            $item['request']['uri'],
95
                            $item['request']['headers'],
96
                            $item['request']['body']
97
                        );
98 22
                        $mockedResponses[] = new $errorClass($item['errorMessage'], $request);
99
                    }
100
                }
101
102 22
                $mockHandler = new MockHandler($mockedResponses);
103 22
                $handler = HandlerStack::create($mockHandler);
104
            }
105
106 22
            $this->client = new Client(['handler' => $handler]);
107
108 22
            if (!$this->shutdownRegistered) {
109 22
                register_shutdown_function(array($this, 'endRecord'));
110 22
                $this->shutdownRegistered = true;
111
            }
112
        }
113
114 22
        return $this->client;
115
    }
116
117
    /**
118
     * Sets the client
119
     *
120
     * @param Client $client
121
     * @return $this
122
     */
123
    public function setHttpClient($client)
124
    {
125
        $this->client = $client;
126
127
        return $this;
128
    }
129
130 25
    public function getRecordLocation()
131
    {
132 25
        if (!$this->recordLocation) {
133 24
            $dir = __DIR__;
134 24
            $dirPos = strrpos($dir, "src/API");
135 24
            $dir = substr($dir, 0, $dirPos);
136
137 24
            $this->recordLocation = $dir . 'Resources/recordings/';
138
        }
139
140 25
        return $this->recordLocation;
141
    }
142
143 25
    public function getRecordFilePath()
144
    {
145 25
        $path = $this->getRecordLocation() . $this->recordFileName;
146 25
        $path = str_replace("\\", "/", $path);
147
148 25
        return $path;
149
    }
150
151 24
    public function getRecordings()
152
    {
153 24
        $saveLocation = $this->getRecordFilePath();
154 24
        $records = json_decode(file_get_contents($saveLocation), true);
155
156 22
        return $records;
157
    }
158
159 1
    public function endRecord()
160
    {
161 1
        if ($this->mode != 'record') {
162 1
            return;
163
        }
164
165 1
        $saveList = [];
166 1
        foreach ($this->callList as $item) {
167
            /** @var Response $response */
168
            $response = $item['response'];
169
170
            if (!isset($item['error'])) {
171
                $save = [
172
                    'error' => false,
173
                    'statusCode' => $response->getStatusCode(),
174
                    'headers' => $response->getHeaders(),
175
                    'body' => $response->getBody()->__toString()
176
                ];
177
            } else {
178
                $save = [
179
                    'error' => true,
180
                    'errorClass' => get_class($item['error']),
181
                    'errorMessage' => $item['error']->getMessage(),
182
                    'request' => [
183
                        'method' => $item['request']->getMethod(),
184
                        'uri' => $item['request']->getUri()->__toString(),
185
                        'headers' => $item['request']->getHeaders(),
186
                        'body' => $item['request']->getBody()->__toString()
187
                    ]
188
                ];
189
            }
190 1
            $saveList[] = $save;
191
        }
192
193 1
        $saveLocation = $this->getRecordFilePath();
194 1
        $folder = pathinfo($saveLocation)['dirname'];
195 1
        if (!is_dir($folder)) {
196 1
            mkdir($folder, 0777, true);
197
        }
198
199 1
        file_put_contents($saveLocation, json_encode($saveList));
200
    }
201
}
202