BaseResponse::getXRequestID()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
/**
3
 * BaseResponse class
4
 */
5
namespace Twigger\UnionCloud\API\Response;
6
7
use Carbon\Carbon;
8
use GuzzleHttp\Psr7\Request;
9
use GuzzleHttp\Psr7\Response;
10
use Twigger\UnionCloud\API\Exception\BaseUnionCloudException;
11
use Twigger\UnionCloud\API\Exception\Request\IncorrectRequestParameterException;
12
use Twigger\UnionCloud\API\Exception\Resource\ResourceNotFoundException;
13
use Twigger\UnionCloud\API\ResourceCollection;
14
use Twigger\UnionCloud\API\Exception\Response\IncorrectResponseTypeException;
15
16
/**
17
 * Handle processing a response and creating Resource classes out of the response
18
 *
19
 * Class BaseResponse
20
 *
21
 * @package Twigger\UnionCloud\API\Core\Responses
22
 */
23
class BaseResponse
24
{
25
26
    /*
27
   |--------------------------------------------------------------------------
28
   | Debug Parameters
29
   |--------------------------------------------------------------------------
30
   |
31
   | Parameters to aid with debugging
32
   |
33
   */
34
    /**
35
     * Response from GuzzleHTTP
36
     * @var Response
37
     */
38
    private $response;
39
40
    /**
41
     * Request from GuzzleHTTP
42
     *
43
     * @var Request
44
     */
45
    private $request;
46
47
    /**
48
     * Data returned from the API
49
     *
50
     * @var array
51
     */
52
    private $rawData;
53
54
    /**
55
     * MetaData returned from the API
56
     * @var array
57
     */
58
    private $rawMeta;
59
60
    /**
61
     * Options passed into Guzzle HTTP
62
     * @var array
63
     */
64
    private $requestOptions;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
    /*
81
   |--------------------------------------------------------------------------
82
   | MetaData Parameters
83
   |--------------------------------------------------------------------------
84
   |
85
   | Parameters to do with the metadata
86
   |
87
   */
88
    /**
89
     * Status code of the request
90
     *
91
     * @var int
92
     */
93
    private $statusCode;
94
95
    /**
96
     * X-Request-ID from the response
97
     * @var string
98
     */
99
    private $xRequestID;
100
101
    /**
102
     * RunTime on the UnionCloud server
103
     * @var double
104
     */
105
    private $runTime;
106
107
    /**
108
     * Date in the HTTP Header
109
     *
110
     * @var Carbon
111
     */
112
    private $responseDate;
113
114
    /**
115
     * Number of records per page
116
     *
117
     * @var int
118
     */
119
    private $recordsPerPage;
120
121
    /**
122
     * Total pages returned
123
     * @var int
124
     */
125
    private $totalPages;
126
127
    /**
128
     * Total number of records returned
129
     * @var int
130
     */
131
    private $totalRecords;
132
133
    /**
134
     * Number of failed records
135
     *
136
     * @var int
137
     */
138
    private $failedRecords;
139
140
    /**
141
     * Number of successful records
142
     *
143
     * @var int
144
     */
145
    private $successfulRecords;
146
147
    /**
148
     * Is the request able to use the pagination functions?
149
     *
150
     * @var bool
151
     */
152
    private $hasPagination = false;
153
154
155
156
    /*
157
   |--------------------------------------------------------------------------
158
   | Resource settings and container
159
   |--------------------------------------------------------------------------
160
   |
161
   | Parameters concerning resources and which classes can handle resources
162
   |
163
   */
164
165
    /**
166
     * Class to treat as the resource handler
167
     *
168
     * @var string
169
     */
170
    private $resourceClass;
171
172
    /**
173
     * Collection of resource classes representing UnionCloud objects
174
     *
175
     * @var ResourceCollection
176
     */
177
    protected $resources;
178
179
180
181
182
183
184
185
186
187
188
189
190
191
    /*
192
   |--------------------------------------------------------------------------
193
   | Ready to parse a response
194
   |--------------------------------------------------------------------------
195
   |
196
   | Load up the details ready to parse a response
197
   |
198
   */
199
200
    /**
201
     * BaseResponse constructor.
202
     *
203
     * Saves the resource class to use, response, request and request options.
204
     * Also saves the response body
205
     *
206
     * @param Response $response Response from Guzzle
207
     * @param Request $request Request from Guzzle
208
     * @param array $requestOptions Guzzle HTTP Options
209
     * @param string $resourceClass Class that implements IResource
210
     *
211
     * @throws IncorrectResponseTypeException
212
     */
213
    public function __construct($response, $request, $requestOptions, $resourceClass)
214
    {
215
        if (!$response instanceof Response)
216
        {
217
            throw new IncorrectResponseTypeException('Request class didn\'t pass a response type into the response', 500);
218
        }
219
        if (!$request instanceof Request)
220
        {
221
            throw new IncorrectResponseTypeException('Request class didn\'t pass a request type into the response', 500);
222
        }
223
224
        $this->resourceClass = $resourceClass;
225
        $this->response = $response;
226
        $this->request = $request;
227
        $this->requestOptions = $requestOptions;
228
        $this->saveResponseBody();
229
230
    }
231
232
    /**
233
     * Saves the response body
234
     *
235
     * Split the response body into data and meta, and save it
236
     * as properties of this class
237
     *
238
     * @return void
239
     */
240
    private function saveResponseBody()
241
    {
242
        $body = $this->response->getBody()->getContents();
243
        if (is_string($body))
244
        {
245
            $body = json_decode($body, true);
246
        }
247
        $this->rawData = $body['data'];
248
        $this->rawMeta = $body['meta'];
249
250
    }
251
252
253
254
255
256
    /*
257
   |--------------------------------------------------------------------------
258
   | Parse a Response
259
   |--------------------------------------------------------------------------
260
   |
261
   | Execute the parsing of a response
262
   |
263
   */
264
265
    ########################### Controller ############################
266
267
    /**
268
     * Entry into instructing the Response to parse the data
269
     *
270
     * @return void
271
     */
272
    protected function parseResponse()
273
    {
274
        // Process MetaData
275
        $this->processMetadata();
276
277
        // Unfortunately, UnionCloud often returns 200 when an error occured (such as the requested resource wasn't found)
278
        // We can look at the body of the response to extract any errors
279
        $this->throwIfErrors();
280
281
        $this->resources = $this->parseResources();
282
    }
283
284
    ########################### Parse the raw metadata ############################
285
    /**
286
     * Process the metadata and save it.
287
     */
288
    private function processMetadata()
289
    {
290
        $this->statusCode = (int) $this->response->getStatusCode();
291
        $this->responseDate = Carbon::parse($this->getHeaderFromResponse('Date'));
292
        $this->runTime = (double) $this->getHeaderFromResponse('X-Runtime');
293
        $this->xRequestID = $this->getHeaderFromResponse('X-Request-ID');
294
295
        if ($this->responseContainsPagination())
296
        {
297
            $this->hasPagination = true;
298
            $this->recordsPerPage = (int) $this->getHeaderFromResponse('records_per_page');
299
            $this->totalPages = (int) $this->getHeaderFromResponse('total_pages');
300
        }
301
302
        $this->totalRecords = (int) $this->getRawMeta()['Total'];
303
        $this->failedRecords = (int) $this->getRawMeta()['Failure'];
304
        $this->successfulRecords = (int) $this->getRawMeta()['Success'];
305
    }
306
307
    /**
308
     * Gets a header from the Guzzle Response
309
     *
310
     * @param string $headerName
311
     *
312
     * @return mixed
313
     */
314
    private function getHeaderFromResponse($headerName)
315
    {
316
        return $this->response->getHeader($headerName)[0];
317
    }
318
319
    /**
320
     * Check if the response is able to use the pagination functions
321
     *
322
     * @return bool
323
     */
324
    public function responseContainsPagination()
325
    {
326
        if (
327
            array_key_exists('records_per_page', $this->response->getHeaders())
328
            &&
329
            array_key_exists('total_records', $this->response->getHeaders())
330
            &&
331
            array_key_exists('total_pages', $this->response->getHeaders())
332
        )
333
        {
334
            return true;
335
        }
336
        return false;
337
    }
338
339
    /**
340
     * Get the raw meta data (i.e. the Summary)
341
     *
342
     * @return mixed
343
     */
344
    public function getRawMeta()
345
    {
346
        return $this->rawMeta['Summary'];
347
    }
348
349
    /**
350
     * Throw errors if there were some from the response
351
     *
352
     * Guzzle catches any errors documented by the status code. Therefore,
353
     * the only place to look for errors is in the response body.
354
     *
355
     * Since all API calls may return different errors, the rules defined
356
     * below may not be universal. If you spot an error, creating a pull
357
     * request with a fix would be hugely appreciated!
358
     *
359
     * Similarly, not all errors may be documented. If you spot an error from
360
     * UnionCloud that slips through, a pull request would be awesome.
361
     *
362
     * @throws ResourceNotFoundException
363
     * @throws BaseUnionCloudException
364
     */
365
    private function throwIfErrors()
366
    {
367
368
        // If no data was returned, no resource was found
369
        if($this->getRawData() === null)
370
        {
371
            throw new ResourceNotFoundException('The resource wasn\'t found', 404);
372
        }
373
374
        $responseBody = (array_key_exists(0, $this->getRawData())?$this->getRawData()[0]:$this->getRawData());
375
376
        // Process the standard error code response.
377
378
        if(array_key_exists('errors', $responseBody) || array_key_exists('error', $responseBody))
379
        {
380
            $errors = [];
381
            // Get the errors
382
            if(array_key_exists('errors', $responseBody))
383
            {
384
                $errors = $responseBody['errors'];
385
            } elseif(array_key_exists('error', $responseBody))
386
            {
387
                $errors = $responseBody['error'];
388
            }
389
390
            // Standardize the errors. If the errors aren't in an enclosing array, put them in one so we can iterate through them
391
            if(! array_key_exists(0, $errors))
392
            {
393
                $errors = [$errors];
394
            }
395
396
            // Throw the error
397
            // TODO allow all errors to be seen by the user
398
            foreach($errors as $error)
399
            {
400
                if(array_key_exists('error_code', $error) && array_key_exists('error_message', $error))
401
                {
402
                    $this->throwCustomUnionCloudError($error);
403
                }
404
            }
405
406
407
            // Default throw if error_code or error_message is missing
408
            throw new BaseUnionCloudException('Couldn\'t parse the UnionCloud response: '.json_encode($this->getRawData()), 500);
409
410
        }
411
    }
412
413
    /**
414
     * Throws an error depending on the error returned from UnionCloud
415
     *
416
     * If the error code wasn't understood, throws a generic error with the
417
     * raw information from UnionCloud
418
     *
419
     * @param array $error single error from UnionCloud
420
     *
421
     * @throws BaseUnionCloudException
422
     */
423
    private function throwCustomUnionCloudError($error)
424
    {
425
        $errorCode = $error['error_code'];
426
        $errorMessage = $error['error_message'];
427
        if(($errorDetails = $this->getUnionCloudErrorDetails($errorCode)) !== false)
428
        {
429
            throw new $errorDetails['errorClass']($errorDetails['message'], $errorDetails['code'], null, $errorCode, $errorMessage);
430
        }
431
432
433
        throw new BaseUnionCloudException($error['error_message'], 500, null, $errorCode);
434
    }
435
436
    /**
437
     * Gets specific details about an error given the error code
438
     *
439
     * @param string $errorCode
440
     *
441
     * @return array|bool false if no error documented, or
442
     *      ['errorClass'=>'..Exception::class', 'code'=>'HTTP code', 'message' => 'Error Message'
443
     */
444
    private function getUnionCloudErrorDetails($errorCode)
445
    {
446
        $errors = [
447
            '401' => [
448
                IncorrectRequestParameterException::class,
449
                401,
450
                'Invalid Email or Password'
451
            ],
452
            '402' => [
453
                IncorrectRequestParameterException::class,
454
                401,
455
                'Invalid App ID or Password'
456
            ],
457
            '403' => [
458
                IncorrectRequestParameterException::class,
459
                401,
460
                'You need further API permissions'
461
            ],
462
            '404' => [
463
                IncorrectRequestParameterException::class,
464
                500,
465
                'Unknown error authenticating'
466
            ],
467
            '405' => [
468
                IncorrectRequestParameterException::class,
469
                401,
470
                'Authentication parameters missing'
471
            ],
472
            '413' => [
473
                IncorrectRequestParameterException::class,
474
                429,
475
                'Too many requests'
476
            ],
477
            'ERR101' => [
478
                IncorrectRequestParameterException::class,
479
                400,
480
                'Something went wrong with your email'
481
            ],
482
            'ERR102' => [
483
                IncorrectRequestParameterException::class,
484
                400,
485
                'Something went wrong with your forename'
486
            ],
487
            'ERR103' => [
488
                IncorrectRequestParameterException::class,
489
                400,
490
                'Something went wrong with your surname'
491
            ],
492
            'ERR104' => [
493
                IncorrectRequestParameterException::class,
494
                400,
495
                'Something went wrong with your DoB'
496
            ],
497
            'ERR105' => [
498
                IncorrectRequestParameterException::class,
499
                400,
500
                'Something went wrong with your gender'
501
            ],
502
            'ERR106' => [
503
                IncorrectRequestParameterException::class,
504
                400,
505
                'Something went wrong with your additional identities'
506
            ],
507
            'ERR107' => [
508
                IncorrectRequestParameterException::class,
509
                400,
510
                'Something went wrong with your institution email'
511
            ],
512
            'ERR108' => [
513
                IncorrectRequestParameterException::class,
514
                400,
515
                'Something went wrong with your student ID'
516
            ],
517
            'ERR109' => [
518
                IncorrectRequestParameterException::class,
519
                400,
520
                'Something went wrong with your nationality'
521
            ],
522
            'ERR110' => [
523
                IncorrectRequestParameterException::class,
524
                400,
525
                'Something went wrong with your Domicile Country'
526
            ],
527
            'ERR111' => [
528
                IncorrectRequestParameterException::class,
529
                400,
530
                'Something went wrong with your fee status'
531
            ],
532
            'ERR112' => [
533
                IncorrectRequestParameterException::class,
534
                400,
535
                'Something went wrong with your study type'
536
            ],
537
            'ERR113' => [
538
                IncorrectRequestParameterException::class,
539
                400,
540
                'Something went wrong with your programme level'
541
            ],
542
            'ERR114' => [
543
                IncorrectRequestParameterException::class,
544
                400,
545
                'Something went wrong with your course end date'
546
            ],
547
            'ERR115' => [
548
                IncorrectRequestParameterException::class,
549
                400,
550
                'Something went wrong with your alternate email address'
551
            ],
552
            'ERR116' => [
553
                IncorrectRequestParameterException::class,
554
                400,
555
                'Something went wrong with your library card'
556
            ],
557
            'ERR117' => [
558
                IncorrectRequestParameterException::class,
559
                400,
560
                'Something went wrong with your erasmus status'
561
            ],
562
            'ERR118' => [
563
                IncorrectRequestParameterException::class,
564
                400,
565
                'Something went wrong with your finalist status'
566
            ],
567
            'ERR119' => [
568
                IncorrectRequestParameterException::class,
569
                400,
570
                'Something went wrong with your mode of study'
571
            ],
572
            'ERR120' => [
573
                IncorrectRequestParameterException::class,
574
                400,
575
                'Something went wrong with your placement status'
576
            ],
577
            'ERR121' => [
578
                IncorrectRequestParameterException::class,
579
                400,
580
                'Something went wrong with your record type'
581
            ],
582
            'ERR122' => [
583
                IncorrectRequestParameterException::class,
584
                404,
585
                'No user found'
586
            ],
587
            'ERR123' => [
588
                IncorrectRequestParameterException::class,
589
                400,
590
                'Something went wrong with your NUS communication status'
591
            ],
592
            'ERR124' => [
593
                IncorrectRequestParameterException::class,
594
                400,
595
                'Something went wrong with your NUS commercial communication status'
596
            ],
597
            'ERR125' => [
598
                IncorrectRequestParameterException::class,
599
                400,
600
                'Something went wrong with your union communication status'
601
            ],
602
            'ERR126' => [
603
                IncorrectRequestParameterException::class,
604
                400,
605
                'Something went wrong with your union commercial communication status'
606
            ],
607
            'ERR127' => [
608
                IncorrectRequestParameterException::class,
609
                400,
610
                'Something went wrong with your terms and conditions'
611
            ],
612
            'ERR201' => [
613
                ResourceNotFoundException::class,
614
                404,
615
                'Group ID wasn\'t found'
616
            ],
617
            'ERR203' => [
618
                IncorrectRequestParameterException::class,
619
                404,
620
                'Membership type ID not found or approved'
621
            ],
622
            'ERR205' => [
623
                IncorrectRequestParameterException::class,
624
                400,
625
                'Next of Kin forename can\'t be blank'
626
            ],
627
            'ERR206' => [
628
                IncorrectRequestParameterException::class,
629
                400,
630
                'Next of Kin surname can\'t be blank'
631
            ],
632
            'ERR207' => [
633
                IncorrectRequestParameterException::class,
634
                400,
635
                'Next of Kin relationship can\'t be blank'
636
            ],
637
            'ERR208' => [
638
                IncorrectRequestParameterException::class,
639
                400,
640
                'Next of Kin address can\'t be blank'
641
            ],
642
            'ERR209' => [
643
                IncorrectRequestParameterException::class,
644
                400,
645
                'Next of Kin home phone can\'t be blank'
646
            ],
647
            'ERR212' => [
648
                IncorrectRequestParameterException::class,
649
                400,
650
                'You need to be over 18 to join this group'
651
            ],
652
            'ERR213' => [
653
                IncorrectRequestParameterException::class,
654
                400,
655
                'Please answer all mandatory questions'
656
            ],
657
            'ERR301' => [
658
                IncorrectRequestParameterException::class,
659
                400,
660
                'Something went wrong with the UserGroup name'
661
            ],
662
            'ERR302' => [
663
                ResourceNotFoundException::class,
664
                400,
665
                'Folder can\'t be found'
666
            ],
667
            'ERR304' => [
668
                ResourceNotFoundException::class,
669
                404,
670
                'UserGroup can\'t be found'
671
            ],
672
            'ERR305' => [
673
                IncorrectRequestParameterException::class,
674
                400,
675
                'Unable to delete - contains a reference to another resource'
676
            ],
677
            'ERR306' => [
678
                IncorrectRequestParameterException::class,
679
                400,
680
                'Unable to delete - system generated UserGroup'
681
            ],
682
            'ERR307' => [
683
                IncorrectRequestParameterException::class,
684
                400,
685
                'Unable to delete - folder not empty'
686
            ],
687
            'ERR308' => [
688
                IncorrectRequestParameterException::class,
689
                400,
690
                'Expiry date is required'
691
            ],
692
            'ERR309' => [
693
                IncorrectRequestParameterException::class,
694
                400,
695
                'UID is required'
696
            ],
697
            'ERR310' => [
698
                IncorrectRequestParameterException::class,
699
                404,
700
                'UserGroup not found'
701
            ],
702
            'ERR311' => [
703
                IncorrectRequestParameterException::class,
704
                400,
705
                'Cannot modify this UserGroups UserGroup Memberships'
706
            ],
707
            'ERR312' => [
708
                IncorrectRequestParameterException::class,
709
                400,
710
                'UserGroup Membership already exists'
711
            ],
712
            'ERR313' => [
713
                IncorrectRequestParameterException::class,
714
                404,
715
                'UserGroup Membership ID not found'
716
            ],
717
            'ERR501' => [
718
                IncorrectRequestParameterException::class,
719
                400,
720
                'Event name cannot be more than 255 characters'
721
            ],
722
            'ERR502' => [
723
                IncorrectRequestParameterException::class,
724
                400,
725
                'Event Type ID is mandatory'
726
            ],
727
            'ERR503' => [
728
                IncorrectRequestParameterException::class,
729
                400,
730
                'Start date not valid'
731
            ],
732
            'ERR504' => [
733
                IncorrectRequestParameterException::class,
734
                400,
735
                'End date not valid'
736
            ],
737
            'ERR505' => [
738
                IncorrectRequestParameterException::class,
739
                400,
740
                'Description is required, and can\'t be longer than 8000 characters'
741
            ],
742
            'ERR506' => [
743
                IncorrectRequestParameterException::class,
744
                400,
745
                'Event name is mandatory'
746
            ],
747
            'ERR507' => [
748
                IncorrectRequestParameterException::class,
749
                400,
750
                'Contact details are mandatory'
751
            ],
752
            'ERR508' => [
753
                IncorrectRequestParameterException::class,
754
                400,
755
                'The capaciy is incorrect'
756
            ],
757
            'ERR511' => [
758
                IncorrectRequestParameterException::class,
759
                400,
760
                'Published date should be in the future'
761
            ],
762
        ];
763
764
        if(array_key_exists($errorCode, $errors))
765
        {
766
            $error = $errors[$errorCode];
767
            return [
768
                'errorClass' => $error[0],
769
                'code' => $error[1],
770
                'message' => $error[2]
771
            ];
772
        }
773
774
        return false;
775
    }
776
    /**
777
     * Interface to the resource.
778
     *
779
     * Will return a collection of all the resources populated with data
780
     *
781
     * @return ResourceCollection
782
     */
783
    private function parseResources()
784
    {
785
        $resources = new ResourceCollection();
786
        // TODO This will throw an error if data wasn't returned in an array
787
788
        try {
789
            foreach ($this->getRawData() as $resource) {
790
                $parsedResource = $this->parseResource($resource);
791
                $resources->addResource($parsedResource);
792
            }
793
        } catch(\Exception $e) {
794
            // See the above TODO
795
        }
796
        return $resources;
797
    }
798
799
    /**
800
     * Parse a single resource, given an array of parameters
801
     *
802
     * @param $resource
803
     *
804
     * @return mixed
805
     */
806
    private function parseResource($resource)
807
    {
808
809
        $resourceClass = new $this->resourceClass($resource);
810
811
        return $resourceClass;
812
813
    }
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
    /*
829
    |--------------------------------------------------------------------------
830
    | Get Details
831
    |--------------------------------------------------------------------------
832
    |
833
    | Execute the parsing of a response
834
    |
835
    */
836
837
838
    /**
839
     * Get the date returned by the server
840
     *
841
     * @return Carbon
842
     */
843
    public function getResponseDate()
844
    {
845
        return $this->responseDate;
846
    }
847
848
    /**
849
     * Get the time taken for the server to complete the task
850
     *
851
     * @return float
852
     */
853
    public function getRunTime()
854
    {
855
        return $this->runTime;
856
    }
857
858
    /**
859
     * Get the X-Request-ID from the response
860
     *
861
     * @return string
862
     */
863
    public function getXRequestID()
864
    {
865
        return $this->xRequestID;
866
    }
867
868
    /**
869
     * Get the Status Code of the request
870
     *
871
     * @return int
872
     */
873
    public function getStatusCode()
874
    {
875
        return $this->statusCode;
876
    }
877
878
    /**
879
     * Get the data from the API call
880
     *
881
     * @return array
882
     */
883
    public function getRawData()
884
    {
885
        return $this->rawData;
886
    }
887
888
889
    /**
890
     * Get the request
891
     *
892
     * @return Request
893
     */
894
    public function getRawRequest()
895
    {
896
        return $this->request;
897
    }
898
899
    /**
900
     * Get the response
901
     *
902
     * @return Response
903
     */
904
    public function getRawResponse()
905
    {
906
        return $this->response;
907
    }
908
909
    /**
910
     * Get the request options passed to Guzzle HTTP
911
     *
912
     * @return array
913
     */
914
    public function getRequestOptions()
915
    {
916
        return $this->requestOptions;
917
    }
918
919
    /**
920
     * Get the total number of pages for a pagination request
921
     *
922
     * @return int
923
     */
924
    public function getTotalPages()
925
    {
926
        return $this->totalPages;
927
    }
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
    /*
943
    |--------------------------------------------------------------------------
944
    | Returning Resources
945
    |--------------------------------------------------------------------------
946
    |
947
    | Functions to return resources
948
    |
949
    */
950
951
952
    /**
953
     * Remove options if debug isn't on
954
     */
955
    public function removeDebugOptions()
956
    {
957
        unset($this->response);
958
        unset($this->request);
959
        unset($this->rawData);
960
        unset($this->rawMeta);
961
        unset($this->requestOptions);
962
    }
963
964
    /**
965
     * Get the returned resources
966
     *
967
     * @return ResourceCollection
968
     */
969
    public function get()
970
    {
971
        return $this->resources;
972
    }
973
974
}