Completed
Push — master ( 42a4de...b05bb8 )
by Gareth
03:31
created

HttpPlayback   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 78.7%

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 24
c 2
b 1
f 1
lcom 1
cbo 6
dl 0
loc 190
ccs 85
cts 108
cp 0.787
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A setHttpClient() 0 6 1
A getRecordFilePath() 0 7 1
A getRecordings() 0 7 1
A getInstance() 0 17 3
A setPlaybackOptions() 0 19 4
C getHttpClient() 0 42 7
A getRecordLocation() 0 12 2
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 33
    public static function getInstance($options = [])
32
    {
33 33
        foreach (self::$instances as $instance) {
34 33
            if ($instance['options'] == $options) {
35 16
                return $instance['instance'];
36
            }
37 33
        }
38
39 29
        $instance = new static();
40 29
        $instance->setPlaybackOptions($options);
41 29
        self::$instances[] = [
42 29
            'instance' => $instance,
43
            'options' => $options
44 29
        ];
45
46 29
        return $instance;
47
    }
48
49 30
    public function setPlaybackOptions($options = [])
50
    {
51 30
        $options = array_replace_recursive(
52 30
            ['mode' => null, 'recordLocation' => null, 'recordFileName' => null],
53
            $options
54 30
        );
55
56 30
        if ($options['mode'] !== null) {
57 30
            $this->mode = $options['mode'];
58 30
        }
59
60 30
        if ($options['recordLocation'] !== null) {
61 1
            $this->recordLocation = $options['recordLocation'];
62 1
        }
63
64 30
        if ($options['recordFileName'] !== null) {
65 30
            $this->recordFileName = $options['recordFileName'];
66 30
        }
67 30
    }
68
69
    /**
70
     * Get the client for making calls
71
     *
72
     * @return Client
73
     */
74 26
    public function getHttpClient()
75
    {
76 26
        if ($this->client == null) {
77 26
            $handler = HandlerStack::create();
78
79 26
            if ($this->mode == 'record') {
80
                $history = Middleware::history($this->callList);
81
                $handler->push($history);
82 26
            } elseif ($this->mode == 'playback') {
83 26
                $recordings = $this->getRecordings();
84
85 26
                $playList = $recordings;
86 26
                $mockedResponses = [];
87 26
                foreach ($playList as $item) {
88 26
                    if (!$item['error']) {
89 25
                        $mockedResponses[] = new Response($item['statusCode'], $item['headers'], $item['body']);
90 25
                    } else {
91 2
                        $errorClass = $item['errorClass'];
92 2
                        $request = new Request(
93 2
                            $item['request']['method'],
94 2
                            $item['request']['uri'],
95 2
                            $item['request']['headers'],
96 2
                            $item['request']['body']
97 2
                        );
98 2
                        $mockedResponses[] = new $errorClass($item['errorMessage'], $request);
99
                    }
100 26
                }
101
102 26
                $mockHandler = new MockHandler($mockedResponses);
103 26
                $handler = HandlerStack::create($mockHandler);
104 26
            }
105
106 26
            $this->client = new Client(['handler' => $handler]);
107
108 26
            if (!$this->shutdownRegistered) {
109 26
                register_shutdown_function(array($this, 'endRecord'));
110 26
                $this->shutdownRegistered = true;
111 26
            }
112 26
        }
113
114 26
        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 27
    public function getRecordLocation()
131
    {
132 27
        if (!$this->recordLocation) {
133 26
            $dir = __DIR__;
134 26
            $dirPos = strrpos($dir, "src/API");
135 26
            $dir = substr($dir, 0, $dirPos);
136
137 26
            $this->recordLocation = $dir.'Resources/recordings/';
138 26
        }
139
140 27
        return $this->recordLocation;
141
    }
142
143 27
    public function getRecordFilePath()
144
    {
145 27
        $path = $this->getRecordLocation().$this->recordFileName;
146 27
        $path = str_replace("\\", "/", $path);
147
148 27
        return $path;
149
    }
150
151 26
    public function getRecordings()
152
    {
153 26
        $saveLocation = $this->getRecordFilePath();
154 26
        $records = json_decode(file_get_contents($saveLocation), true);
155
156 26
        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
            $saveList[] = $save;
191 1
        }
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 1
        }
198
199 1
        file_put_contents($saveLocation, json_encode($saveList));
200 1
    }
201
}
202