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

Client::getEvent()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 16
rs 9.8666
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