Completed
Push — master ( ae4a40...cd3ab6 )
by Tristan
13:24 queued 09:52
created

RestClient::getHttpClient()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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