Completed
Push — master ( dbd16b...a17da9 )
by Steven
02:08
created

Client   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 273
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 100%

Importance

Changes 7
Bugs 0 Features 0
Metric Value
wmc 22
c 7
b 0
f 0
lcom 1
cbo 12
dl 0
loc 273
ccs 75
cts 75
cp 1
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A applyConfiguration() 0 6 1
A getAuthorizationHeader() 0 8 2
A getConfigForVerbAndParameters() 0 16 3
A getHeaders() 0 7 1
A getUrlFromPath() 0 8 3
A handleRequestException() 0 11 2
A parseConfiguration() 0 12 1
A parseRateLimitFromResponse() 0 13 2
A request() 0 17 2
A setHttpClient() 0 5 1
A enforceSandboxExpectation() 0 8 3
1
<?php namespace Stevenmaguire\Uber;
2
3
use GuzzleHttp\Client as HttpClient;
4
use GuzzleHttp\Exception\ClientException as HttpClientException;
5
use GuzzleHttp\Psr7\Response;
6
use ReflectionClass;
7
8
class Client
9
{
10
    use GetSetTrait;
11
    use Resources\Estimates;
12
    use Resources\Products;
13
    use Resources\Promotions;
14
    use Resources\Reminders;
15
    use Resources\Requests;
16
    use Resources\Riders;
17
18
    /**
19
     * Access token
20
     *
21
     * @var string
22
     */
23
    private $access_token;
24
25
    /**
26
     * Server token
27
     *
28
     * @var string
29
     */
30
    private $server_token;
31
32
    /**
33
     * Use sandbox API
34
     *
35
     * @var bool
36
     */
37
    private $use_sandbox;
38
39
    /**
40
     * Version
41
     *
42
     * @var string
43
     */
44
    private $version;
45
46
    /**
47
     * Locale
48
     *
49
     * @var string
50
     */
51
    private $locale;
52
53
    /**
54
     * Rate limit
55
     *
56
     * @var RateLimit
57
     */
58
    private $rate_limit = null;
59
60
    /**
61
     * Http client
62
     *
63
     * @var HttpClient
64
     */
65
    private $http_client;
66
67
    /**
68
     * Create new client
69
     *
70
     * @param array $configuration
71
     */
72 94
    public function __construct($configuration = [])
73
    {
74 94
        $configuration = $this->parseConfiguration($configuration);
75 94
        $this->applyConfiguration($configuration);
76 94
        $this->http_client = new HttpClient;
77 94
    }
78
79
    /**
80
     * Apply configuration
81
     *
82
     * @param  array $configuration
83
     *
84
     * @return void
85
     */
86
    private function applyConfiguration($configuration = [])
87
    {
88 94
        array_walk($configuration, function ($value, $key) {
89 94
            $this->updateAttribute($key, $value);
90 94
        });
91 94
    }
92
93
    /**
94
     * Get authorization header value
95
     *
96
     * @return string
97
     */
98 72
    private function getAuthorizationHeader()
99
    {
100 72
        if ($this->access_token) {
101 2
            return 'Bearer '.$this->access_token;
102
        }
103
104 70
        return 'Token '.$this->server_token;
105
    }
106
107
    /**
108
     * Get HttpClient config for verb and parameters
109
     *
110
     * @param  string $verb
111
     * @param  array  $parameters
112
     *
113
     * @return array
114
     */
115 62
    private function getConfigForVerbAndParameters($verb, $parameters = [])
116
    {
117
        $config = [
118 62
            'headers' => $this->getHeaders()
119 62
        ];
120
121 62
        if (!empty($parameters)) {
122 30
            if (strtolower($verb) == 'get') {
123 10
                $config['query'] = $parameters;
124 10
            } else {
125 20
                $config['json'] = $parameters;
126
            }
127 30
        }
128
129 62
        return $config;
130
    }
131
132
    /**
133
     * Get headers for request
134
     *
135
     * @return array
136
     */
137 72
    public function getHeaders()
138
    {
139
        return [
140 72
            'Authorization' => trim($this->getAuthorizationHeader()),
141 72
            'Accept-Language' => trim($this->locale),
142 72
        ];
143
    }
144
145
    /**
146
     * Build url
147
     *
148
     * @param  string   $path
149
     *
150
     * @return string   Url
151
     */
152 66
    public function getUrlFromPath($path)
153
    {
154 66
        $path = ltrim($path, '/');
155
156 66
        $host = 'https://'.($this->use_sandbox ? 'sandbox-' : '').'api.uber.com';
157
158 66
        return $host.($this->version ? '/'.$this->version : '').'/'.$path;
159
    }
160
161
    /**
162
     * Handle http client exceptions
163
     *
164
     * @param  HttpClientException $e
165
     *
166
     * @return void
167
     * @throws Exception
168
     */
169 6
    private function handleRequestException(HttpClientException $e)
170
    {
171 6
        if ($response = $e->getResponse()) {
172 4
            $exception = new Exception($response->getReasonPhrase(), $response->getStatusCode(), $e);
173 4
            $exception->setBody(json_decode($response->getBody()));
174
175 4
            throw $exception;
176
        }
177
178 2
        throw new Exception($e->getMessage(), 500, $e);
179
    }
180
181
    /**
182
     * Parse configuration using defaults
183
     *
184
     * @param  array $configuration
185
     *
186
     * @return array $configuration
187
     */
188 94
    private function parseConfiguration($configuration = [])
189
    {
190
        $defaults = array(
191 94
            'access_token'  =>  null,
192 94
            'server_token'  =>  null,
193 94
            'use_sandbox'   =>  false,
194 94
            'version'   =>  'v1.2',
195 94
            'locale'    => 'en_US',
196 94
        );
197
198 94
        return array_merge($defaults, $configuration);
199
    }
200
201
    /**
202
     * Attempt to pull rate limit headers from response and add to client
203
     *
204
     * @param  Response  $response
205
     *
206
     * @return void
207
     */
208 56
    private function parseRateLimitFromResponse(Response $response)
209
    {
210 56
        $rateLimitHeaders = array_filter([
211 56
            $response->getHeader('X-Rate-Limit-Limit'),
212 56
            $response->getHeader('X-Rate-Limit-Remaining'),
213 56
            $response->getHeader('X-Rate-Limit-Reset')
214 56
        ]);
215
216 56
        if (count($rateLimitHeaders) == 3) {
217 34
            $rateLimitClass = new ReflectionClass(RateLimit::class);
218 34
            $this->rate_limit = $rateLimitClass->newInstanceArgs($rateLimitHeaders);
219 34
        }
220 56
    }
221
222
    /**
223
     * Makes a request to the Uber API and returns the response
224
     *
225
     * @param    string $verb       The Http verb to use
226
     * @param    string $path       The path of the APi after the domain
227
     * @param    array  $parameters Parameters
228
     *
229
     * @return   stdClass The JSON response from the request
230
     * @throws   Exception
231
     */
232 62
    private function request($verb, $path, $parameters = [])
233
    {
234 62
        $client = $this->http_client;
235 62
        $url = $this->getUrlFromPath($path);
236 62
        $verb = strtolower($verb);
237 62
        $config = $this->getConfigForVerbAndParameters($verb, $parameters);
238
239
        try {
240 62
            $response = $client->$verb($url, $config);
241 62
        } catch (HttpClientException $e) {
242 6
            $this->handleRequestException($e);
243
        }
244
245 56
        $this->parseRateLimitFromResponse($response);
246
247 56
        return json_decode($response->getBody());
248
    }
249
250
    /**
251
     * Set Http Client
252
     *
253
     * @param HttpClient  $client
254
     *
255
     * @return Client
256
     */
257 62
    public function setHttpClient(HttpClient $client)
258
    {
259 62
        $this->http_client = $client;
260 62
        return $this;
261
    }
262
263
    /**
264
     * Throws exception when client is not configured sandbox use. Should only
265
     * be utilized when attempting to do work against ephemeral sandbox API
266
     * data.
267
     *
268
     * @see    https://developer.uber.com/docs/riders/guides/sandbox
269
     * @return void
270
     * @throws Exception
271
     */
272 8
    private function enforceSandboxExpectation($message = null)
273
    {
274 8
        if (!$this->use_sandbox) {
275 4
            $message = $message ?: 'Attempted to invoke sandbox functionality '.
276 4
                'with production client; this is not recommended';
277 4
            throw new Exception($message);
278
        }
279 4
    }
280
}
281