Passed
Push — scrutinizer ( 3b62b8...241763 )
by
unknown
08:40 queued 52s
created

Client   F

Complexity

Total Complexity 74

Size/Duplication

Total Lines 501
Duplicated Lines 0 %

Test Coverage

Coverage 24.37%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 208
dl 0
loc 501
ccs 48
cts 197
cp 0.2437
rs 2.48
c 8
b 0
f 0
wmc 74

15 Methods

Rating   Name   Duplication   Size   Complexity  
A setLogging() 0 3 1
F getEvents() 0 122 28
A getClassPass() 0 16 3
A setGuzzleClient() 0 3 1
A setToken() 0 7 2
A getClassPasses() 0 17 3
A getLocations() 0 17 3
A request() 0 22 4
A getLocation() 0 15 3
B getAttachments() 0 29 9
A getTicket() 0 17 3
A __construct() 0 39 4
A getEvent() 0 16 3
A getAttachment() 0 15 3
A getTickets() 0 23 4

How to fix   Complexity   

Complex Class

Complex classes like Client 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.

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 Client, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace InShore\Bookwhen;
6
7
use GuzzleHttp;
8
use GuzzleHttp\Client as GuzzleClient;
9
use GuzzleHttp\Psr7\Request;
10
use InShore\Bookwhen\Exceptions\ConfigurationException;
11
use InShore\Bookwhen\Exceptions\RestException;
12
use InShore\Bookwhen\Exceptions\ValidationException;
13
use InShore\Bookwhen\Interfaces\ClientInterface;
14
use InShore\Bookwhen\Validator;
15
use InShore\Bookwhen\Exceptions\InshoreBookwhenException;
16
use Monolog\Logger;
17
use Monolog\Handler\StreamHandler;
18
use Psr\Http\Message\ResponseInterface;
19
20
21
/**
22
 * Class Client
23
 *
24
 * The main class for API consumption
25
 *
26
 * @package inshore\bookwhen
27
 * @todo comments
28
 * @todo externalise config
29
 * @todo fix token
30
 */
31
class Client implements ClientInterface
32
{
33
    
34
    /** @var string The API access token */
35
    private static $token = null;
36
    
37
    /** @var string The instance token, settable once per new instance */
38
    private $instanceToken;
39
    
40
    private $apiBaseUri;
41
    
42
    private $apiQuery;
43
   
44
    private $apiResource;
45
    
46
    private $apiVersion;
47
48
    private $include;
49
    
50
    /** @var string The path to the log file */
51
    private $log;
52
    
53
    /** @var object loging object. */
54
    private $logger;
55
    
56
    /** @var string the logging level. */
57
    private $logging;
58
    
59
    private $validator;
60
    
61
    private $guzzleClient;
62
    
63
    /**
64
     * @param string|null $token The API access token, as obtained on diffbot.com/dev
65
     * @throws DiffbotException When no token is provided
66
     */
67
    public function __construct($token = null)
68
    {
69
        
70
        $this->apiBaseUri = 'https://api.bookwhen.com/';
71
            
72
        $this->apiQuery = [];
73
        
74
        $this->apiVersion = 'v2';
75
76
        $this->include = [];
77
        
78
        $this->validator = new Validator();
79
        
80
        $this->guzzleClient = new GuzzleClient([
81
            'base_uri' => $this->apiBaseUri
82
        ]);
83
        
84
        if ($token === null) {
85
//             if (self::$token === null) {
86
//                 $msg = 'No token provided, and none is globally set. ';
87
//                 $msg .= 'Use Diffbot::setToken, or instantiate the Diffbot class with a $token parameter.';
88
//                 throw new ConfigurationException($msg);
89
//             }
90
        } else {
91
            if ($this->validator->validToken($token)) {
92
                self::$token = $token;
93
                $this->instanceToken = self::$token;
94
            }
95
        }
96
        
97
        if (empty($this->logging)) {
98
            $this->logging = 'debug';
99
            $this->log = 'inShoreBookwhen.log';
100
        }
101
        
102
        $this->logger = new Logger('inShore Bookwhen API');
103
        $this->logger->pushHandler(new StreamHandler($this->log, Logger::DEBUG));
104
        $this->logger->info('Client class successfully instantiated');
105
        $this->logger->debug(var_export($this, true));
106
    }
107
    
108
    /**
109
     * @todo debug flag
110
     */
111
    protected function request(): ResponseInterface
112
    {
113
        try {
114
            // Authorization.
115
            $requestOptions = [
116
                'headers' => [
117
                    'Authorization' => 'Basic ' . base64_encode($this->instanceToken . ':')
118
                ]
119
            ];
120
            
121
            // Query.
122
            if (!empty($this->apiQuery) && is_array($this->apiQuery)) {
123
                $requestOptions['query'] = $this->apiQuery;
124
            }
125
   
126
            $this->logger->debug('request(GET, ' . $this->apiResource . ', ' . var_export($requestOptions, true) . ')');
127
            $requestOptions['debug'] = true;
128
            
129
            return $this->guzzleClient->request('GET', $this->apiResource, $requestOptions);
130
           
131
        } catch (Exception $e) {
132
            throw new RestException($e, $this->logger);
133
        }
134
    }
135
    
136
    /**
137
     * {@inheritDoc}
138
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getAttachment()
139
     */
140 2
    public function getAttachment($attachmentId)
141
    {
142 2
        if (!$this->validator->validId($attachmentId, 'attachment')) {
143 1
            throw new ValidationException('attachmentId', $attachmentId);
144
        }
145 1
        $this->apiResource = $this->apiVersion . '/attachments' . '/' . $attachmentId;
146
     
147
        try {
148 1
            $Response = $this->request();
149 1
            $body = json_decode($Response->getBody()->getContents());
150 1
            $attachment = $body->data[0];
151 1
            $return = $attachment;
152 1
            return $return;
153
        } catch (Exception $e) {
154
            throw new RestException($e, $this->logger);
155
        }
156
    }
157
    
158
    /**
159
     *
160
     * {@inheritDoc}
161
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getAttachments()
162
     * @todo is ! empty then tests each optional param and write validator method.
163
     */
164 1
    public function getAttachments($title = null, $fileName = null, $fileType = null): array
165
    {    
166 1
        if (!is_null($title) && !$this->validator->validTitle($title)) {
167
            throw new ValidationException('title', $title);
168
        }
169
170 1
        if (!is_null($fileName) && !$this->validator->validFileName($fileName)) {
171
            throw new ValidationException('file name', $fileName);
172
        }
173
174
175 1
        if (!is_null($fileType) && !$this->validator->validFileType($fileType)) {
176
            throw new ValidationException('file type', $fileType);
177
        }
178
        
179 1
        $this->apiResource = $this->apiVersion . '/attachments';
180
        
181
        try {
182 1
            $return = [];
183 1
            $Response = $this->request();
184 1
            $body = json_decode($Response->getBody()->getContents());
185
            
186 1
            foreach ($body->data as $attachment) {
187 1
                array_push($return, $attachment);
188
            }
189
            
190 1
            return $return;
191
        } catch (Exception $e) {
192
            throw new RestException($e, $this->logger);
193
        }
194
    }
195
    
196
    /**
197
     *
198
     * {@inheritDoc}
199
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getClassPass()
200
     */
201
    public function getClassPass($classPassId)
202
    {
203
        $this->apiResource = $this->apiVersion . '/class_passes';
204
       
205
        if (!$this->validator->validId($classPassId, 'classPass')) {
206
            throw new ValidationException('classPassId', $classPassId);
207
        }
208
     
209
        try {
210
            $Response = $this->request();
211
            $body = json_decode($Response->getBody()->getContents());
212
            $classPass = $body->data[0];
213
            $return = $classPass;
214
            return $return;
215
        } catch (Exception $e) {
216
            throw new RestException($e->getMessage(), $this->logger);
217
        }
218
    }
219
    
220
    /**
221
     *
222
     * {@inheritDoc}
223
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getClassPasses()
224
     * @todo break params on to multiplper lines..
225
     */
226
    public function getClassPasses(
227
        $title = null, 
228
        $detail = null, 
229
        $usageType, 
230
        $cost = null, 
231
        $usageAllowance = null, 
232
        $useRestrictedForDays = null): array
233
    {   
234
        if (!is_null($title) && !$this->validator->validTitle($title)) {
235
            throw new ValidationException('title', $title);
236
        }
237
       
238
        $this->apiResource = $this->apiVersion . '/???';
239
        
240
        // @todo prepocess response onto nice model objects.
241
        $Response = $this->request();
242
        return json_decode($Response->getBody()->getContents());
243
    }
244
    
245
    /**
246
     *
247
     * {@inheritDoc}
248
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getEvent()
249
     */
250 1
    public function getEvent($eventId)
251
    {
252 1
        if (!$this->validator->validId($eventId, 'event')) {
253
            throw new ValidationException('eventId', $eventId);
254
        }
255 1
        $this->apiResource = $this->apiVersion . '/events' . '/' . $eventId;
256
     
257
        try {
258 1
            $Response = $this->request();
259 1
            $body = json_decode($Response->getBody()->getContents());
260 1
            $event = $body->data;
261 1
            $event->soldOut = (bool) ($event->attributes->attendee_count >= $event->attributes->attendee_limit);
262 1
            $return = $event;
263 1
            return $return;
264
        } catch (Exception $e) {
265
            throw new RestException($e, $this->logger);
266
        }
267
    }
268
    
269
    /**
270
     *
271
     * {@inheritDoc}
272
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getEvents()
273
     */
274
    public function getEvents(
275
        $calendar = false,
276
        $entry = false,
277
        $location = [],
278
        $tags = [],
279
        $title = [],
280
        $detail = [],
281
        $from = null,
282
        $to = null,
283
        $includeLocation = false,
284
        $includeAttachments = false,
285
        $includeTickets = false,
286
        $includeTicketsEvents = false,
287
        $includeTicketsClassPasses = false): array
288
    {    
289
        // Validate $tags.
290
        if (!empty($tags)) {
291
            if (!is_array($tags)) {
292
                throw new ValidationException();
0 ignored issues
show
Bug introduced by
The call to InShore\Bookwhen\Excepti...xception::__construct() has too few arguments starting with key. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

292
                throw /** @scrutinizer ignore-call */ new ValidationException();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
293
            } else {
294
                $tags = array_unique($tags);
295
                foreach ($tags as $tag) {
296
                    if (!empty($tag) && !$this->validator->validTag($tag)) {
297
                        throw new ValidationException('tag', $tag);
298
                    }
299
                }
300
            }
301
            $this->apiQuery['filter[tag]'] = implode(',', $tags);
302
        }
303
        
304
        // Validate $from;
305
        if (!empty($from)) {
306
            if (!$this->validator->validFrom($from, $to)) {
307
                throw new ValidationException('from', $from . '-' . $to);
308
            } else {
309
                $this->apiQuery['filter[from]'] = $from;
310
            }
311
        }
312
        
313
        // Validate $to;
314
        if (!empty($to)) {
315
            if (!$this->validator->validTo($to, $from)) {
316
                throw new ValidationException('to', $to . '-' . $from);
317
            } else {
318
                $this->apiQuery['filter[to]'] = $to;
319
            }
320
        }
321
        
322
        // API resource.
323
        $this->apiResource = $this->apiVersion . '/events';
324
        
325
        
326
        $include = [];
327
        // Validate $includeLocation;
328
329
        if (!empty($includeLocation)) {
330
            if (!$this->validator->validInclude($includeLocation)) {
331
                throw new ValidationException('include', $includeLocation);
332
            } else if($includeLocation) {
333
                $include[] = 'location';
334
            }
335
        }
336
337
        // Validate $includeAttachments;
338
        if (!empty($includeAttachments)) {
339
            if (!$this->validator->validInclude($includeAttachments)) {
340
                throw new ValidationException('include', $includeAttachments);
341
            } else if ($includeAttachments) {
342
                $include[] = 'attachments';
343
            }
344
        }
345
        
346
        // Validate $includeTickets
347
        if (!empty($includeTickets)) {
348
            if (!$this->validator->validInclude($includeTickets)) {
349
                throw new ValidationException('include', $includeTickets);
350
            } else if ($includeTickets) {
351
                    $include[] = 'tickets';
352
            }
353
        }
354
        
355
        // Validate $includeTicketsEvents;
356
        if (!empty($includeTicketsEvents)) {
357
           if (!$this->validator->validInclude($includeTicketsEvents)) {
358
               throw new ValidationException('include', $includeTicketsEvents);
359
           } else if ($includeTicketsEvents) {
360
               $include[] = 'tickets.events';
361
           }
362
        }
363
364
        // Validate $includeTicketsEvents;
365
        if (!empty($includeTicketsClassPasses)) {
366
            if (!$this->validator->validInclude($includeTicketsClassPasses)) {
367
                throw new ValidationException('include', $includeTicketsClassPasses);
368
            } else if ($includeTicketsClassPasses) {
369
                $include[] = 'tickets.class_passes';
370
            }
371
        }
372
373
        if (count($include) > 0) {
374
            $this->apiQuery['include'] = implode(',', $include);
375
376
        }
377
  
378
        try {
379
            $Response = $this->request();
380
            
381
            $body = json_decode($Response->getBody()->getContents());
382
            
383
            // Prepocess response onto nice model objects.
384
            // @todo abstract.
385
            $return = [];
386
            
387
            foreach ($body->data as $event) {
388
                // Add additional properties here.
389
                $event->soldOut = (bool) ($event->attributes->attendee_count >= $event->attributes->attendee_limit);
390
                array_push($return, $event);
391
            }
392
            
393
            return $return;
394
        } catch (Exception $e) {
395
            throw new RestException($e, $this->logger);
396
        }
397
    }
398
    
399
    /**
400
     *
401
     * {@inheritDoc}
402
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getLocation()
403
     */
404
    public function getLocation($locationId)
405
    {
406
        $this->apiResource = $this->apiVersion . '/locations';
407
        if (!$this->validator->validId($locationId, 'location')) {
408
            throw new ValidationException('locationId', $locationId);
409
        }
410
        
411
        try {
412
            $Response = $this->request();
413
            $body = json_decode($Response->getBody()->getContents());
414
            $location = $body->data[0];
415
            $return = $location;
416
            return $return;
417
        } catch (Exception $e) {
418
            throw new RestException($e->getMessage(), $this->logger);
419
        }
420
421
    }
422
    
423
    /**
424
     *
425
     * {@inheritDoc}
426
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getLocations()
427
     * @todo validate params.
428
     */
429
    public function getLocations($addressText = null, $additionalInfo = null): array
430
    {
431
        $this->apiResource = $this->apiVersion . '/locations';
432
433
        $return = [];
434
        
435
        try {
436
            $Response = $this->request();
437
            $body = json_decode($Response->getBody()->getContents());
438
            
439
            foreach ($body->data as $location) {
440
                array_push($return, $location);
441
            }
442
            
443
            return $return;
444
        } catch (Exception $e) {
445
            throw new RestException($e, $this->logger);
446
        }
447
    } 
448
    
449
    /**
450
     *
451
     * {@inheritDoc}
452
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getTicket()
453
     */
454 1
    public function getTicket($ticketId)
455
    {        
456 1
        if (!$this->validator->validId($ticketId, 'ticket')) {
457
            throw new ValidationException('ticketId', $ticketId);
458
        }
459
460 1
        $this->apiResource = $this->apiVersion . '/tickets';
461
462
        
463
        try {
464 1
            $Response = $this->request();
465 1
            $body = json_decode($Response->getBody()->getContents());
466 1
            $ticket = $body->data[0];
467 1
            $return = $ticket;
468 1
            return $return;
469
        } catch (Exception $e) {
470
            throw new RestException($e, $this->logger);
471
        }
472
    }
473
    
474
    /**
475
     * 
476
     * {@inheritDoc}
477
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getTickets()
478
     */
479 1
    public function getTickets($eventId): array
480
    {
481 1
        if (!$this->validator->validId($eventId, 'event')) {
482
            throw new ValidationException('eventId', $eventId);
483
        }
484
485 1
        $this->apiQuery = ['event' => $eventId];
486
        
487 1
        $this->apiResource = $this->apiVersion . '/tickets';
488
                
489
        try {
490 1
            $return = [];
491
            
492 1
            $Response = $this->request();
493 1
            $body = json_decode($Response->getBody()->getContents());
494
            
495 1
            foreach ($body->data as $ticket) {
496 1
                array_push($return, $ticket);
497
            }
498 1
            $this->logger->debug(var_export($return, true));
499 1
            return $return;
500
        } catch (GuzzleHttp\Exception\ClientException $e) {
501
            throw new RestException($e, $this->logger);
502
        }
503
    }
504
    
505
    /**
506
     * Set Debug.
507
     */
508
    public function setLogging($level)
509
    {
510
        $this->logging = $level;
511
    } 
512
    
513
    /**
514
     * Set Guzzle Client
515
     */
516
    public function setGuzzleClient($guzzleClient)
517
    {
518
        $this->guzzleClient = $guzzleClient;
519
    } 
520
    
521
    /**
522
     * Sets the token for all future new instances
523
     * @param $token string The API access token, as obtained on diffbot.com/dev.
524
     */
525
    public static function setToken($token)
526
    {
527
        $validator = new Validator();
528
        if (!$validator->validToken($token)) {
529
            throw new \InvalidArgumentException('Invalid Token.');
530
        }
531
        self::$token = $token;
532
    } 
533
}
534
535
// EOF!
536