Client   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 275
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Test Coverage

Coverage 100%

Importance

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