Completed
Push — master ( 5d29e9...f1fbf7 )
by Tristan
04:58 queued 02:54
created

RestClient::processResponse()   D

Complexity

Conditions 9
Paths 20

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 4.909
c 0
b 0
f 0
cc 9
eloc 15
nc 20
nop 1
1
<?PHP
2
3
/**
4
 * MyPoseo API Bundle
5
 *
6
 * @author Tristan Bessoussa <[email protected]>
7
 */
8
9
namespace Tristanbes\MyPoseoBundle\Connection;
10
11
use Http\Client\HttpClient;
12
use Http\Client\Common\PluginClient;
13
use Psr\Cache\CacheItemPoolInterface;
14
use Psr\Http\Message\ResponseInterface;
15
use Http\Discovery\HttpClientDiscovery;
16
use Http\Discovery\MessageFactoryDiscovery;
17
use Http\Message\Authentication\QueryParam;
18
use Http\Client\Common\Plugin\AuthenticationPlugin;
19
20
use Tristanbes\MyPoseoBundle\Exception\ThrottleLimitException;
21
use Tristanbes\MyPoseoBundle\Exception\NotEnoughCreditsException;
22
23
/**
24
 * This class is a wrapper for the HTTP client.
25
 */
26
class RestClient
27
{
28
    /**
29
     * Your API key.
30
     *
31
     * @var string
32
     */
33
    private $apiKey;
34
35
    /**
36
     * @var HttpClient
37
     */
38
    protected $httpClient;
39
40
    /**
41
     * @var string
42
     */
43
    protected $apiHost;
44
45
    /**
46
     * @var CacheItemPoolInterface
47
     */
48
    protected $cache;
49
50
    /**
51
     * @param string                 $apiKey
52
     * @param string                 $apiHost
53
     * @param HttpClient             $httpClient
54
     * @param CacheItemPoolInterface $cache
55
     */
56
    public function __construct($apiKey, $apiHost, $httpClient = null, CacheItemPoolInterface $cache = null)
57
    {
58
        $this->apiKey     = $apiKey;
59
        $this->apiHost    = $apiHost;
60
        $this->httpClient = $httpClient;
61
        $this->cache      = $cache;
62
    }
63
64
     /**
65
     * @return HttpClient
66
     */
67
    protected function getHttpClient()
68
    {
69
        if ($this->httpClient === null) {
70
            $this->httpClient = HttpClientDiscovery::find();
71
        }
72
73
        $authentication = new QueryParam(['key' => $this->apiKey]);
74
75
        $authenticationPlugin = new AuthenticationPlugin($authentication);
76
77
        $client = new PluginClient($this->httpClient, [$authenticationPlugin]);
78
79
        return $client;
80
    }
81
82
    /**
83
     * Sends the API request if cache not hit
84
     *
85
     * @param string  $method
86
     * @param string  $uri
87
     * @param null    $body
88
     * @param array   $headers
89
     * @param string  $cacheKey
90
     * @param integer $ttl
91
     *
92
     * @return array
93
     */
94
    public function send($method, $uri, $body = null, array $headers = [], $cacheKey = null, $ttl = null)
95
    {
96
        $saveToCache = false;
97
98
        if ($cacheKey !== null && $ttl !== null && $this->cache) {
99
            if ($this->cache->hasItem($cacheKey)) {
100
                return $this->cache->getItem($cacheKey)->get();
101
            } else {
102
                $saveToCache = true;
103
            }
104
        }
105
106
        if (is_array($body)) {
107
            $body = http_build_query($body);
108
            $headers['Content-Type'] = 'application/x-www-form-urlencoded';
109
        }
110
111
        $request = MessageFactoryDiscovery::find()->createRequest($method, $this->getApiUrl($uri), $headers, $body);
112
        $rawResponse = $this->getHttpClient()->sendRequest($request);
113
114
        $data = $this->processResponse($rawResponse);
115
116
        if ($this->cache && true === $saveToCache) {
117
            $item = $this->cache
118
                ->getItem($cacheKey)
119
                ->set($data)
120
                ->expiresAfter($ttl)
121
            ;
122
123
            $this->cache->save($item);
124
        }
125
126
        return $data;
127
    }
128
129
    /**
130
     * Process the API response, provides error handling
131
     *
132
     * @param ResponseInterface $response
133
     *
134
     * @throws \Exception
135
     *
136
     * @return array
137
     */
138
    public function processResponse(ResponseInterface $response)
139
    {
140
        $httpResponseCode = (int) $response->getStatusCode();
141
142
        $data = (string) $response->getBody();
143
        $jsonResponseData = json_decode($data, false);
144
145
        $result = new \stdClass();
146
        // return response data as json if possible, raw if not
147
        $result->http_response_body = $data && $jsonResponseData === null ? $data : $jsonResponseData;
148
        $result->http_response_code = $httpResponseCode;
149
150
        if (isset($jsonResponseData['status']) && $jsonResponseData['status'] != "success") {
151
            throw new \Exception('MyPoseo API: '.$data['message']);
152
        }
153
154
        if (isset($jsonResponseData['myposeo']['code'])) {
155
            if ($jsonResponseData['myposeo']['code'] == '-1' && $jsonResponseData['myposeo']['message'] == 'No enough credits') {
156
                throw new NotEnoughCreditsException();
157
            }
158
159
            if ($jsonResponseData['myposeo']['code'] == '-1') {
160
                throw new ThrottleLimitException();
161
            }
162
        }
163
164
        return $jsonResponseData;
165
    }
166
167
    /**
168
     * @param string       $endpointUrl
169
     * @param array        $queryString
170
     * @param string|null  $cacheKey
171
     * @param integer|null $ttl
172
     *
173
     * @return ResponseInterface
174
     */
175
    public function get($endpointUrl, $queryString = [], $cacheKey = null, $ttl = null)
176
    {
177
        return $this->send('GET', $endpointUrl.'?'.http_build_query($queryString), null, [], $cacheKey, $ttl);
178
    }
179
180
    /**
181
     * @param string $endpointUrl
182
     * @param array  $postData
183
     *
184
     * @return \stdClass
185
     */
186
    public function post($endpointUrl, array $postData = [])
187
    {
188
        $postDataMultipart = [];
189
        foreach ($postData as $key => $value) {
190
            if (is_array($value)) {
191
                $index = 0;
192
                foreach ($value as $subValue) {
193
                    $postDataMultipart[] = [
194
                        'name'     => sprintf('%s[%d]', $key, $index++),
195
                        'contents' => $subValue,
196
                    ];
197
                }
198
            } else {
199
                $postDataMultipart[] = [
200
                    'name'     => $key,
201
                    'contents' => $value,
202
                ];
203
            }
204
        }
205
206
        return $this->send('POST', $endpointUrl, $postDataMultipart);
207
    }
208
209
    /**
210
     * @param $uri
211
     *
212
     * @return string
213
     */
214
    private function getApiUrl($uri)
215
    {
216
        return $this->generateEndpoint($this->apiHost).$uri;
217
    }
218
219
    /**
220
     * @param string $apiEndpoint
221
     *
222
     * @return string
223
     */
224
    private function generateEndpoint($apiEndpoint)
225
    {
226
        return sprintf('%s/', $apiEndpoint);
227
    }
228
}
229