Passed
Push — master ( 13a2e4...3dfb69 )
by Kevin
02:09
created

Request   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 516
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 44
lcom 1
cbo 4
dl 0
loc 516
ccs 116
cts 116
cp 1
rs 8.3396
c 0
b 0
f 0

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 1
A getHttpClient() 0 21 3
A setHandlerStack() 0 4 1
A setLogger() 0 4 1
A setMessageFormatter() 0 4 1
A me() 0 4 1
A updateMe() 0 13 3
A listClients() 0 4 1
A createClient() 0 9 2
A deleteClient() 0 4 1
A listGauges() 0 4 1
A createGauge() 0 4 1
A gaugeDetail() 0 4 1
A updateGauge() 0 4 1
A deleteGauge() 0 4 1
A listShares() 0 4 1
A shareGauge() 0 8 1
A topContent() 0 16 4
A unshareGauge() 0 4 1
A topReferrers() 0 4 1
A traffic() 0 4 1
A browserResolutions() 0 4 1
A technology() 0 4 1
A searchTerms() 0 4 1
A searchEngines() 0 4 1
A locations() 0 4 1
A browserStats() 0 4 1
A makeApiCall() 0 15 1
A formatCommonParameters() 0 17 4
A formatGaugeParameters() 0 20 4

How to fix   Complexity   

Complex Class

Complex classes like Request often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Request, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Kevintweber\Gauges;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\ClientInterface;
7
use GuzzleHttp\HandlerStack;
8
use GuzzleHttp\Middleware;
9
use GuzzleHttp\MessageFormatter;
10
use GuzzleHttp\Psr7\Response;
11
use Psr\Log\LoggerAwareInterface;
12
use Psr\Log\LoggerInterface;
13
use Psr\Log\LogLevel;
14
15
/**
16
 * Used to make Gauges API calls.
17
 */
18
class Request implements LoggerAwareInterface
19
{
20
    const URI = 'https://secure.gaug.es/';
21
22
    /** @var null|ClientInterface */
23
    private $client;
24
25
    /** @var HandlerStack */
26
    private $handlerStack;
27
28
    /** @var null|LoggerInterface */
29
    private $logger;
30
31
    /** @var string */
32
    private $logLevel;
33
34
    /** @var MessageFormatter */
35
    private $messageFormatter;
36
37
    /** @var array */
38
    private $options;
39
40
    /** @var string */
41
    protected $token;
42
43
    /**
44
     * Constructor
45
     *
46
     * @param string $token     Your API token
47
     * @param array  $options   See Guzzle documentation (proxy, etc.)
48
     * @param string $logLevel  PSR3 LogLevel. Default = LogLevel::INFO
49
     */
50 26
    public function __construct(string $token, array $options = array(), string $logLevel = LogLevel::INFO)
51
    {
52 26
        $this->client = null;
53 26
        $this->handlerStack = HandlerStack::create();
54 26
        $this->logger = null;
55 26
        $this->logLevel = $logLevel;
56 26
        $this->messageFormatter = new MessageFormatter();
57 26
        $this->options = array_merge(
58 26
            array('timeout' => 10),
59
            $options
60
        );
61 26
        $this->options['base_uri'] = self::URI;
62 26
        $this->token = $token;
63 26
    }
64
65
    /**
66
     * Getter for the HTTP client.
67
     *
68
     * @return Client
69
     */
70 23
    protected function getHttpClient() : Client
71
    {
72 23
        if ($this->client instanceof Client) {
73 1
            return $this->client;
74
        }
75
76 23
        if ($this->logger instanceof LoggerInterface) {
77 23
            $this->handlerStack->push(
78 23
                Middleware::log(
79 23
                    $this->logger,
80 23
                    $this->messageFormatter,
81 23
                    $this->logLevel
82
                )
83
            );
84
        }
85
86 23
        $this->options['handler'] = $this->handlerStack;
87 23
        $this->client = new Client($this->options);
88
89 23
        return $this->client;
90
    }
91
92
    /**
93
     * Setter for the Guzzle HandlerStack
94
     */
95 25
    public function setHandlerStack(HandlerStack $handlerStack)
96
    {
97 25
        $this->handlerStack = $handlerStack;
98 25
    }
99
100 26
    public function setLogger(LoggerInterface $logger)
101
    {
102 26
        $this->logger = $logger;
103 26
    }
104
105
    /**
106
     * Setter for the Guzzle MessageFormatter
107
     */
108 26
    public function setMessageFormatter(MessageFormatter $messageFormatter)
109
    {
110 26
        $this->messageFormatter = $messageFormatter;
111 26
    }
112
113
    /**
114
     * Get Your Information
115
     *
116
     * Returns your information.
117
     *
118
     * @return Response
119
     */
120 2
    public function me() : Response
121
    {
122 2
        return $this->makeApiCall('GET', 'me');
123
    }
124
125
    /**
126
     * Update Your Information
127
     *
128
     * Updates and returns your information with the updates applied.
129
     *
130
     * @param string $first_name Your first name. (Optional)
131
     * @param string $last_name  Your last name. (Optional)
132
     *
133
     * @return Response
134
     */
135 1
    public function updateMe(string $first_name = null, string $last_name = null) : Response
136
    {
137 1
        $params = array();
138 1
        if (isset($first_name)) {
139 1
            $params['first_name'] = $first_name;
140
        }
141
142 1
        if (isset($last_name)) {
143 1
            $params['last_name'] = $last_name;
144
        }
145
146 1
        return $this->makeApiCall('PUT', 'me', $params);
147
    }
148
149
    /**
150
     * API Client List
151
     *
152
     * Returns an array of your API clients.
153
     *
154
     * @return Response
155
     */
156 1
    public function listClients() : Response
157
    {
158 1
        return $this->makeApiCall('GET', 'clients');
159
    }
160
161
    /**
162
     * Creating an API Client
163
     *
164
     * Creates an API client, which can be used to authenticate against
165
     * the Gaug.es API.
166
     *
167
     * @param string $description Short description for the key (Optional)
168
     *
169
     * @return Response
170
     */
171 1
    public function createClient(string $description = null) : Response
172
    {
173 1
        $params = array();
174 1
        if (isset($description)) {
175 1
            $params['description'] = $description;
176
        }
177
178 1
        return $this->makeApiCall('POST', 'clients', $params);
179
    }
180
181
    /**
182
     * Delete an API Client
183
     *
184
     * Permanently deletes an API client key.
185
     *
186
     * @param string $id
187
     *
188
     * @return Response
189
     */
190 1
    public function deleteClient(string $id) : Response
191
    {
192 1
        return $this->makeApiCall('DELETE', 'clients/' . $id);
193
    }
194
195
    /**
196
     * Gauges List
197
     *
198
     * Returns an array of your gauges, with recent traffic included.
199
     *
200
     * @param int $page Page number (Optional)
201
     *
202
     * @return Response
203
     */
204 1
    public function listGauges(int $page = null) : Response
205
    {
206 1
        return $this->makeApiCall('GET', 'gauges', $this->formatCommonParameters(null, $page));
207
    }
208
209
    /**
210
     * Create a New Gauge
211
     *
212
     * Creates a gauge.
213
     *
214
     * @param string               $title
215
     * @param string|\DateTimeZone $tz
216
     * @param string               $allowedHosts (Optional)
217
     *
218
     * @return Response
219
     */
220 2
    public function createGauge(string $title, $tz, string $allowedHosts = null) : Response
221
    {
222 2
        return $this->makeApiCall('POST', 'gauges', $this->formatGaugeParameters($title, $tz, $allowedHosts));
223
    }
224
225
    /**
226
     * Gauge Detail
227
     *
228
     * Gets details for a gauge.
229
     *
230
     * @param string $id
231
     *
232
     * @return Response
233
     */
234 1
    public function gaugeDetail(string $id) : Response
235
    {
236 1
        return $this->makeApiCall('GET', 'gauges/' . $id);
237
    }
238
239
    /**
240
     * Update a Gauge
241
     *
242
     * Updates and returns a gauge with the updates applied.
243
     *
244
     * @param string               $id
245
     * @param string               $title
246
     * @param string|\DateTimeZone $tz
247
     * @param string               $allowedHosts (Optional)
248
     *
249
     * @return Response
250
     */
251 1
    public function updateGauge(string $id, string $title, $tz, string $allowedHosts = null) : Response
252
    {
253 1
        return $this->makeApiCall('PUT', 'gauges/' . $id, $this->formatGaugeParameters($title, $tz, $allowedHosts));
254
    }
255
256
    /**
257
     * Delete a Gauge
258
     *
259
     * Permanently deletes a gauge.
260
     *
261
     * @param string $id
262
     *
263
     * @return Response
264
     */
265 1
    public function deleteGauge(string $id) : Response
266
    {
267 1
        return $this->makeApiCall('DELETE', 'gauges/' . $id);
268
    }
269
270
    /**
271
     * List Shares
272
     *
273
     * Lists the people that have access to a Gauge.
274
     *
275
     * @param string $id
276
     *
277
     * @return Response
278
     */
279 1
    public function listShares(string $id) : Response
280
    {
281 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/shares');
282
    }
283
284
    /**
285
     * Share a Gauge
286
     *
287
     * Shares gauge with a person by their email. Any valid email will work
288
     * and will receive an invite even if there is no existing Gauges user
289
     * with that email.
290
     *
291
     * @param string $id
292
     * @param string $email
293
     *
294
     * @return Response
295
     */
296 1
    public function shareGauge(string $id, string $email) : Response
297
    {
298
        $params = array(
299 1
            'email' => $email
300
        );
301
302 1
        return $this->makeApiCall('POST', 'gauges/' . $id . '/shares', $params);
303
    }
304
305
    /**
306
     * Top Content
307
     *
308
     * Gets top content for a gauge, paginated.
309
     *
310
     * @param string           $id
311
     * @param string|\DateTime $date  (Optional) Date in format YYYY-MM-DD
312
     * @param string           $group (Optional) Either "day" or "month".  Default is "day".
313
     * @param int              $page  (Optional)
314
     *
315
     * @return Response
316
     */
317 2
    public function topContent(string $id, $date = null, string $group = null, int $page = null) : Response
318
    {
319 2
        $params = $this->formatCommonParameters($date, $page);
320 2
        if (isset($group)) {
321 2
            $group = strtolower($group);
322 2
            if ($group !== 'month' && $group !== 'day') {
323 1
                throw new \InvalidArgumentException(
324 1
                    'Invalid group parameter for "topContent" call.  Allowed values are "day" or "month".  Actual value is : ' . $group
325
                );
326
            }
327
328 1
            $params['group'] = $group;
329
        }
330
331 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/content', $params);
332
    }
333
334
    /**
335
     * Un-share Gauge
336
     *
337
     * @param string $id
338
     * @param string $user_id
339
     *
340
     * @return Response
341
     */
342 1
    public function unshareGauge(string $id, string $user_id) : Response
343
    {
344 1
        return $this->makeApiCall('DELETE', 'gauges/' . $id . '/shares/' . $user_id);
345
    }
346
347
    /**
348
     * Top Referrers
349
     *
350
     * Gets top referrers for a gauge, paginated.
351
     *
352
     * @param string           $id
353
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
354
     * @param int              $page (Optional)
355
     *
356
     * @return Response
357
     */
358 1
    public function topReferrers(string $id, $date = null, int $page = null) : Response
359
    {
360 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/referrers', $this->formatCommonParameters($date, $page));
361
    }
362
363
    /**
364
     * Traffic
365
     *
366
     * Gets traffic for a gauge.
367
     *
368
     * @param string           $id
369
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
370
     *
371
     * @return Response
372
     */
373 1
    public function traffic(string $id, $date = null) : Response
374
    {
375 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/traffic', $this->formatCommonParameters($date));
376
    }
377
378
    /**
379
     * Browser Resolutions
380
     *
381
     * Gets browsers heights, browser widths, and screen widths for a gauge.
382
     *
383
     * @param string $id
384
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
385
     *
386
     * @return Response
387
     */
388 1
    public function browserResolutions(string $id, $date = null) : Response
389
    {
390 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/resolutions', $this->formatCommonParameters($date));
391
    }
392
393
    /**
394
     * Technology
395
     *
396
     * Gets browsers and platforms for a gauge.
397
     *
398
     * @param string           $id
399
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
400
     *
401
     * @return Response
402
     */
403 1
    public function technology(string $id, $date = null) : Response
404
    {
405 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/technology', $this->formatCommonParameters($date));
406
    }
407
408
    /**
409
     * Search Terms
410
     *
411
     * Gets search terms for a gauge, paginated.
412
     *
413
     * @param string $id
414
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
415
     * @param int    $page (Optional)
416
     *
417
     * @return Response
418
     */
419 1
    public function searchTerms(string $id, $date = null, int $page = null) : Response
420
    {
421 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/terms', $this->formatCommonParameters($date, $page));
422
    }
423
424
    /**
425
     * Search Engines
426
     *
427
     * Gets search engines for a gauge.
428
     *
429
     * @param string $id
430
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
431
     *
432
     * @return Response
433
     */
434 1
    public function searchEngines(string $id, $date = null) : Response
435
    {
436 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/engines', $this->formatCommonParameters($date));
437
    }
438
439
    /**
440
     * Locations
441
     *
442
     * Gets locations for a gauge.
443
     *
444
     * @param string $id
445
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
446
     *
447
     * @return Response
448
     */
449 1
    public function locations(string $id, $date = null) : Response
450
    {
451 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/locations', $this->formatCommonParameters($date));
452
    }
453
454
    /**
455
     * Browser stats
456
     *
457
     * Get the browser statistics in a format used with the browserlist module.
458
     * (See https://github.com/ai/browserslist)
459
     *
460
     * @param string $id
461
     * @param string|\DateTime $date (Optional) Date in format YYYY-MM-DD
462
     *
463
     * @return Response
464
     */
465 1
    public function browserStats(string $id, $date = null) : Response
466
    {
467 1
        return $this->makeApiCall('GET', 'gauges/' . $id . '/browserstats', $this->formatCommonParameters($date));
468
    }
469
470
    /**
471
     * Make the actual gauges API call.
472
     *
473
     * @param string $method       [GET|POST|PUT|DELETE]
474
     * @param string $path
475
     * @param array  $params
476
     *
477
     * @return Response
478
     */
479 23
    protected function makeApiCall(string $method, string $path, array $params = array()) : Response
480
    {
481
        // Format method.
482 23
        $method = strtoupper($method);
483
484
        // Make API call.
485 23
        return $this->getHttpClient()->request(
486
            $method,
487
            $path,
488
            array(
489 23
                'headers' => array('X-Gauges-Token' => $this->token),
490 23
                'query' => $params
491
            )
492
        );
493
    }
494
495 11
    private function formatCommonParameters($date = null, int $page = null) : array
496
    {
497 11
        $params = array();
498 11
        if (isset($date)) {
499 10
            if (!$date instanceof \DateTime) {
500 10
                $date = new \DateTime($date);
501
            }
502
503 10
            $params['date'] = $date->format('Y-m-d');
504
        }
505
506 11
        if (isset($page)) {
507 4
            $params['page'] = $page;
508
        }
509
510 11
        return $params;
511
    }
512
513 3
    private function formatGaugeParameters(string $title, $tz, string $allowedHosts = null) : array
514
    {
515 3
        if (empty($title)) {
516 1
            throw new \InvalidArgumentException('Gauge title must not be empty.');
517
        }
518
519 2
        if (!$tz instanceof \DateTimeZone) {
520 2
            $tz = new \DateTimeZone($tz);
521
        }
522
523
        $params = array(
524 2
            'title' => $title,
525 2
            'tz' => $tz->getName()
526
        );
527 2
        if (isset($allowedHosts)) {
528 2
            $params['allowed_hosts'] = $allowedHosts;
529
        }
530
531 2
        return $params;
532
    }
533
}
534