Passed
Pull Request — develop (#59)
by
unknown
09:35
created

Client::getEvents()   F

Complexity

Conditions 23
Paths 3328

Size

Total Lines 127
Code Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 23
eloc 58
nc 3328
nop 13
dl 0
loc 127
rs 0
c 2
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
    private $validator;
51
    
52
    private $guzzleClient;
53
    
54
    /**
55
     * @param string|null $token The API access token, as obtained on diffbot.com/dev
56
     * @throws DiffbotException When no token is provided
57
     */
58
    public function __construct($token = null)
59
    {
60
        
61
        $this->apiBaseUri = 'https://api.bookwhen.com/';
62
            
63
        $this->apiQuery = [];
64
        
65
        $this->apiVersion = 'v2';
66
67
        $this->include = [];
68
        
69
        $this->validator = new Validator();
70
        
71
        $this->guzzleClient = new GuzzleClient([
72
            'base_uri' => $this->apiBaseUri
73
        ]);
74
        
75
        if ($token === null) {
76
            if (self::$token === null) {
0 ignored issues
show
introduced by
The condition self::token === null is always false.
Loading history...
77
                $msg = 'No token provided, and none is globally set. ';
78
                $msg .= 'Use Diffbot::setToken, or instantiate the Diffbot class with a $token parameter.';
79
                throw new ConfigurationException($msg);
80
            }
81
        } else {
82
            if ($this->validator->validToken($token)) {
83
                self::$token = $token;
84
                $this->instanceToken = self::$token;
85
            }
86
        }
87
        
88
        if (empty($this->logging)) {
89
            $this->logging = 'debug';
0 ignored issues
show
Bug Best Practice introduced by
The property logging does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
90
            $this->log = 'inShoreBookwhen.log';
0 ignored issues
show
Bug Best Practice introduced by
The property log does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
91
        }
92
        
93
        $this->logger = new Logger('inShore Bookwhen API');
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
94
        $this->logger->pushHandler(new StreamHandler($this->log, Logger::DEBUG ));
95
        $this->logger->info('Client class successfully instantiated');
96
        $this->logger->debug(var_export($this, true));
97
    }
98
    
99
    /**
100
     * @todo debug flag
101
     */
102
    protected function request(): ResponseInterface
103
    {
104
        try {
105
            // Authorization.
106
            $requestOptions = [
107
                'headers' => [
108
                    'Authorization' => 'Basic ' . base64_encode($this->instanceToken . ':')
109
                ]
110
            ];
111
            
112
            // Query.
113
            if (!empty($this->apiQuery) && is_array($this->apiQuery)) {
114
                $requestOptions['query'] = $this->apiQuery;
115
            }
116
   
117
            $this->logger->debug('request(GET, ' . $this->apiResource . ', ' . var_export($requestOptions, true) . ')');
118
            //$requestOptions['debug'] = true;
119
            
120
            return $this->guzzleClient->request('GET', $this->apiResource, $requestOptions);
121
           
122
        } catch (Exception $e) {
123
            throw new RestException($e, $this->logger);
124
        }
125
    }
126
    
127
    /**
128
     * @todo
129
     */
130
    public function getAttachment($attachmentId)
131
    {
132
        if (!$this->validator->validId($attachmentId, 'attachment')) {
133
            throw new ValidationException('attachmentId', $attachmentId);
0 ignored issues
show
Bug introduced by
'attachmentId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

133
            throw new ValidationException(/** @scrutinizer ignore-type */ 'attachmentId', $attachmentId);
Loading history...
134
        }
135
        $this->apiResource = $this->apiVersion . '/attachments' . '/' . $attachmentId;
136
     
137
        try {
138
            $Response = $this->request();
139
            $body = json_decode($Response->getBody()->getContents());
140
            $attachment = $body->data[0];
141
            $return = $attachment;
142
            return $return;
143
        } catch (Exception $e) {
144
            throw new RestException($e, $this->logger);
145
        }
146
    }
147
    
148
    /**
149
     *
150
     * {@inheritDoc}
151
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getAttachments()
152
     * @todo is ! empty then tests each optional param and write validator method.
153
     */
154
    public function getAttachments($title = null, $fileName = null, $fileType = null): array
155
    {    
156
        if (!is_null($title) && !$this->validator->validTitle($title)) {
157
            throw new ValidationException('title', $title);
0 ignored issues
show
Bug introduced by
'title' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

157
            throw new ValidationException(/** @scrutinizer ignore-type */ 'title', $title);
Loading history...
158
        }
159
160
        if(!is_null($fileName) && !$this->validator->validFileName($fileName)) {
161
            throw new ValidationException('file name', $fileName);
162
        }
163
164
165
        if(!is_null($fileType) && !$this->validator->validFileType($fileType)) {
166
            throw new ValidationException('file type', $fileType);
167
        }
168
        
169
        $this->apiResource = $this->apiVersion . '/attachments';
170
        
171
        try {
172
            $return = [];
173
            $Response = $this->request();
174
            $body = json_decode($Response->getBody()->getContents());
175
            
176
            foreach ($body->data as $attachment) {
177
                array_push($return, $attachment);
178
            }
179
            
180
            return $return;
181
        } catch (Exception $e) {
182
            throw new RestException($e, $this->logger);
183
        }
184
    }
185
    
186
    /**
187
     *
188
     * {@inheritDoc}
189
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getClassPass()
190
     */
191
    public function getClassPass($classPassId)
192
    {
193
        $this->apiResource = $this->apiVersion . '/class_passes';
194
       
195
        if (!$this->validator->validId($classPassId, 'classPass')) {
196
            throw new ValidationException('classPassId', $classPassId);
0 ignored issues
show
Bug introduced by
'classPassId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

196
            throw new ValidationException(/** @scrutinizer ignore-type */ 'classPassId', $classPassId);
Loading history...
197
        }
198
     
199
        try {
200
            $Response = $this->request();
201
            $body = json_decode($Response->getBody()->getContents());
202
            $classPass = $body->data[0];
203
            $return = $classPass;
204
            return $return;
205
        } catch (Exception $e) {
206
            throw new RestException($e->getMessage());
0 ignored issues
show
Bug introduced by
The call to InShore\Bookwhen\Excepti...xception::__construct() has too few arguments starting with logger. ( Ignorable by Annotation )

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

206
            throw /** @scrutinizer ignore-call */ new RestException($e->getMessage());

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...
207
        }
208
    }
209
    
210
    /**
211
     *
212
     * {@inheritDoc}
213
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getClassPasses()
214
     * @todo break params on to multiplper lines..
215
     */
216
    public function getClassPasses(
217
        $title = null, 
218
        $detail = null, 
219
        $usageType, 
220
        $cost = null, 
221
        $usageAllowance = null, 
222
        $useRestrictedForDays = null): array
223
    {   
224
        if (!is_null($title) && !$this->validator->validTitle($title)) {
225
            throw new ValidationException('title', $title);
0 ignored issues
show
Bug introduced by
'title' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

225
            throw new ValidationException(/** @scrutinizer ignore-type */ 'title', $title);
Loading history...
226
        }
227
       
228
        $this->apiResource = $this->apiVersion . '/???';
229
        
230
        // @todo prepocess response onto nice model objects.
231
        $Response = $this->request();
232
        return json_decode($Response->getBody()->getContents());
233
    }
234
    
235
    /**
236
     *
237
     * {@inheritDoc}
238
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getEvent()
239
     */
240
    public function getEvent($eventId)
241
    {
242
        if (!$this->validator->validId($eventId, 'event')) {
243
            throw new ValidationException('eventId', $eventId);
0 ignored issues
show
Bug introduced by
'eventId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

243
            throw new ValidationException(/** @scrutinizer ignore-type */ 'eventId', $eventId);
Loading history...
244
        }
245
        $this->apiResource = $this->apiVersion . '/events' . '/' . $eventId;
246
     
247
        try {
248
            $Response = $this->request();
249
            $body = json_decode($Response->getBody()->getContents());
250
            $event = $body->data;
251
            $event->soldOut = (bool) ($event->attributes->attendee_count >= $event->attributes->attendee_limit);
252
            $return = $event;
253
            return $return;
254
        } catch (Exception $e) {
255
            throw new RestException($e, $this->logger);
256
        }
257
    }
258
    
259
    /**
260
     *
261
     * {@inheritDoc}
262
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getEvents()
263
     */
264
    public function getEvents(
265
        $calendar = false,
266
        $entry = false,
267
        $location = [],
268
        $tags = [],
269
        $title = [],
270
        $detail = [],
271
        $from = null,
272
        $to = null,
273
        $includeLocation = false,
274
        $includeAttachments = false,
275
        $includeTickets = false,
276
        $includeTicketsEvents = false,
277
        $includeTicketsClassPasses = false): array
278
    {    
279
        // Validate $tags.
280
        if (!empty($tags)) {
281
            if (!is_array($tags)) {
282
                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

282
                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...
283
            } else {
284
                $tags = array_unique($tags);
285
                foreach ($tags as $tag) {
286
                    if (!empty($tag) && !$this->validator->validTag($tag)) {
287
                        throw new ValidationException();
288
                    }
289
                }
290
            }
291
            $this->apiQuery['filter[tag]'] = implode(',', $tags);
292
        }
293
        
294
        // Validate $from;
295
        if (!empty($from)) {
296
            if (!$this->validator->validFrom($from, $to)) {
297
                throw new ValidationException('from', $from . '-' . $to);
0 ignored issues
show
Bug introduced by
$from . '-' . $to of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $value of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

297
                throw new ValidationException('from', /** @scrutinizer ignore-type */ $from . '-' . $to);
Loading history...
Bug introduced by
'from' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

297
                throw new ValidationException(/** @scrutinizer ignore-type */ 'from', $from . '-' . $to);
Loading history...
298
            } else {
299
                $this->apiQuery['filter[from]'] = $from;
300
            }
301
        }
302
        
303
        // Validate $to;
304
        if (!empty($to)) {
305
            if (!$this->validator->validTo($to, $from)) {
306
                throw new ValidationException('to', $to . '-' . $from);
307
            } else {
308
                $this->apiQuery['filter[to]'] = $to;
309
            }
310
        }
311
        
312
        // API resource.
313
        $this->apiResource = $this->apiVersion . '/events';
314
        
315
        
316
        $include = [];
317
        // Validate $includeLocation;
318
319
        if (!empty($includeLocation)) {
320
            if(!$this->validator->validInclude($includeLocation)) {
321
                throw new ValidationException('include', $includeLocation);
322
            } else {
323
                $include[] = 'location';
324
            }
325
        }
326
327
                // Validate $includeAttachments;
328
329
330
        if (!empty($includeAttachments)) {
331
            if(!$this->validator->validInclude($includeAttachments)) {
332
                throw new ValidationException('include', $includeAttachments);
333
            } else {
334
                $include[] = 'attachments';
335
            }
336
        }
337
        
338
        // Validate $includeTickets;
339
340
        if (!empty($includeTickets)) {
341
            if(!$this->validator->validInclude($includeTickets)) {
342
                throw new ValidationException('include', $includeTickets);
343
            } else {
344
                $include[] = 'tickets';
345
            }
346
        }
347
        
348
         // Validate $includeTicketsEvents;
349
350
         if (!empty($includeTicketsEvents)) {
351
            if(!$this->validator->validInclude($includeTicketsEvents)) {
352
                throw new ValidationException('include', $includeTicketsEvents);
353
            } else {
354
                $include[] = 'tickets.events';
355
            }
356
        }
357
358
         // Validate $includeTicketsEvents;
359
360
         if (!empty($includeTicketsClassPasses)) {
361
            if(!$this->validator->validInclude($includeTicketsClassPasses)) {
362
                throw new ValidationException('include', $includeTicketsClassPasses);
363
            } else {
364
                $include[] = 'tickets.class_passes';
365
            }
366
        }
367
368
        if (count($include) > 0) {
369
            $this->apiQuery['include'] = implode(',', $include);
370
371
        }
372
  
373
        try {
374
            $Response = $this->request();
375
            
376
            $body = json_decode($Response->getBody()->getContents());
377
            
378
            // Prepocess response onto nice model objects.
379
            // @todo abstract.
380
            $return = [];
381
            
382
            foreach ($body->data as $event) {
383
                // Add additional properties here.
384
                $event->soldOut = (bool) ($event->attributes->attendee_count >= $event->attributes->attendee_limit);
385
                array_push($return, $event);
386
            }
387
            
388
            return $return;
389
        } catch (Exception $e) {
390
            throw new RestException($e, $this->logger);
391
        }
392
    }
393
    
394
    /**
395
     *
396
     * {@inheritDoc}
397
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getLocation()
398
     */
399
    public function getLocation($locationId)
400
    {
401
        $this->apiResource = $this->apiVersion . '/locations';
402
        if (!$this->Validator->validId($locationId, 'location')) {
0 ignored issues
show
Bug introduced by
The property Validator does not exist on InShore\Bookwhen\Client. Did you mean validator?
Loading history...
403
            throw new ValidationException('locationId', $locationId);
0 ignored issues
show
Bug introduced by
'locationId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

403
            throw new ValidationException(/** @scrutinizer ignore-type */ 'locationId', $locationId);
Loading history...
404
        }
405
        
406
        try {
407
            $Response = $this->request();
408
            $body = json_decode($Response->getBody()->getContents());
409
            $location = $body->data[0];
410
            $return = $location;
411
            return $return;
412
        } catch (Exception $e) {
413
            throw new RestException($e->getMessage());
0 ignored issues
show
Bug introduced by
The call to InShore\Bookwhen\Excepti...xception::__construct() has too few arguments starting with logger. ( Ignorable by Annotation )

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

413
            throw /** @scrutinizer ignore-call */ new RestException($e->getMessage());

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...
414
        }
415
416
    }
417
    
418
    /**
419
     *
420
     * {@inheritDoc}
421
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getLocations()
422
     * @todo validate params.
423
     */
424
    public function getLocations($addressText = null, $additionalInfo = null): array
425
    {
426
        $this->apiResource = $this->apiVersion . '/locations';
427
428
        $return = [];
429
        
430
        try {
431
            $Response = $this->request();
432
            $body = json_decode($Response->getBody()->getContents());
433
            
434
            foreach ($body->data as $location) {
435
                array_push($return, $location);
436
            }
437
            
438
            return $return;
439
        } catch (Exception $e) {
440
            throw new RestException($e, $this->logger);
441
        }
442
    } 
443
    
444
    /**
445
     *
446
     * {@inheritDoc}
447
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getTicket()
448
     */
449
    public function getTicket($ticketId)
450
    {        
451
        if (!$this->validator->validId($ticketId, 'ticket')) {
452
            throw new ValidationException('ticketId', $ticketId);
0 ignored issues
show
Bug introduced by
'ticketId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

452
            throw new ValidationException(/** @scrutinizer ignore-type */ 'ticketId', $ticketId);
Loading history...
453
        }
454
455
        $this->apiResource = $this->apiVersion . '/tickets';
456
457
        
458
        try {
459
            $Response = $this->request();
460
            $body = json_decode($Response->getBody()->getContents());
461
            $ticket = $body->data[0];
462
            $return = $ticket;
463
            return $return;
464
        } catch (Exception $e) {
465
            throw new RestException($e, $this->logger);
466
        }
467
    }
468
    
469
    /**
470
     * 
471
     * {@inheritDoc}
472
     * @see \InShore\Bookwhen\Interfaces\ClientInterface::getTickets()
473
     */
474
    public function getTickets($eventId): array
475
    {
476
        if (!$this->validator->validId($eventId, 'event')) {
477
            throw new ValidationException('eventId', $eventId);
0 ignored issues
show
Bug introduced by
'eventId' of type string is incompatible with the type InShore\Bookwhen\Exceptions\unknown expected by parameter $key of InShore\Bookwhen\Excepti...xception::__construct(). ( Ignorable by Annotation )

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

477
            throw new ValidationException(/** @scrutinizer ignore-type */ 'eventId', $eventId);
Loading history...
478
        }
479
480
        $this->apiQuery = ['event' => $eventId];
481
        
482
        $this->apiResource = $this->apiVersion . '/tickets';
483
                
484
        try {
485
            $return = [];
486
            
487
            $Response = $this->request();
488
            $body = json_decode($Response->getBody()->getContents());
489
            
490
            foreach ($body->data as $ticket) {
491
                array_push($return, $ticket);
492
            }
493
            $this->logger->debug(var_export($return, true));
494
            return $return;
495
        } catch (GuzzleHttp\Exception\ClientException $e) {
496
            throw new RestException($e, $this->logger);
497
        }
498
    }
499
    
500
    /**
501
     * Set Debug.
502
     */
503
    public function setLogging($level)
504
    {
505
        $this->logging = $level;
0 ignored issues
show
Bug Best Practice introduced by
The property logging does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
506
    } 
507
    
508
    /**
509
     * Set Guzzle Client
510
     */
511
    public function setGuzzleClient($guzzleClient)
512
    {
513
        $this->guzzleClient = $guzzleClient;
514
    } 
515
    
516
    /**
517
     * Sets the token for all future new instances
518
     * @param $token string The API access token, as obtained on diffbot.com/dev.
519
     */
520
    public static function setToken($token)
521
    {
522
        $validator = new Validator();
523
        if (!$validator->validToken($token)) {
524
            throw new \InvalidArgumentException('Invalid Token.');
525
        }
526
        self::$token = $token;
527
    } 
528
}
529
530
// EOF!
531