Test Failed
Push — master ( b58c54...db9131 )
by Jodie
04:37 queued 01:35
created

Smokescreen::collection()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
c 0
b 0
f 0
rs 8.5125
cc 6
eloc 15
nc 10
nop 3
1
<?php
2
3
namespace Rexlabs\Laravel\Smokescreen;
4
5
use Illuminate\Contracts\Support\Arrayable;
6
use Illuminate\Contracts\Support\Jsonable;
7
use Illuminate\Contracts\Support\Responsable;
8
use Illuminate\Database\Eloquent\Builder;
9
use Illuminate\Database\Eloquent\Collection;
10
use Illuminate\Database\Eloquent\Model;
11
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
12
use Illuminate\Database\Eloquent\Relations\HasMany;
13
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
14
use Illuminate\Database\Eloquent\Relations\Relation;
15
use Illuminate\Http\JsonResponse;
16
use Illuminate\Http\Request;
17
use Illuminate\Http\Response;
18
use Illuminate\Pagination\LengthAwarePaginator;
19
use Illuminate\Support\Arr;
20
use Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException;
21
use Rexlabs\Laravel\Smokescreen\Pagination\Paginator as PaginatorBridge;
22
use Rexlabs\Laravel\Smokescreen\Relations\RelationLoader;
23
use Rexlabs\Laravel\Smokescreen\Resources\CollectionResource;
24
use Rexlabs\Laravel\Smokescreen\Resources\ItemResource;
25
use Rexlabs\Smokescreen\Exception\MissingResourceException;
26
use Rexlabs\Smokescreen\Helpers\JsonHelper;
27
use Rexlabs\Smokescreen\Relations\RelationLoaderInterface;
28
use Rexlabs\Smokescreen\Resource\Item;
29
use Rexlabs\Smokescreen\Resource\ResourceInterface;
30
use Rexlabs\Smokescreen\Serializer\SerializerInterface;
31
use Rexlabs\Smokescreen\Transformer\TransformerInterface;
32
33
/**
34
 * Smokescreen for Laravel.
35
 * Tightly integrates the rexlabs/smokescreen resource transformation library with the Laravel framework.
36
 *
37
 * @author    Jodie Dunlop <[email protected]>
38
 * @copyright Rex Software 2018
39
 */
40
class Smokescreen implements \JsonSerializable, Jsonable, Arrayable, Responsable
41
{
42
    const TYPE_ITEM_RESOURCE = 'item';
43
    const TYPE_COLLECTION_RESOURCE = 'collection';
44
    const TYPE_AMBIGUOUS_RESOURCE = 'ambiguous';
45
46
    /** @var \Rexlabs\Smokescreen\Smokescreen */
47
    protected $smokescreen;
48
49
    /** @var string|null */
50
    protected $includes;
51
52
    /** @var string|bool Whether includes should be parsed from a request key */
53
    protected $autoParseIncludes = true;
54
55
    /** @var SerializerInterface|null */
56
    protected $serializer;
57
58
    /** @var Request|null */
59
    protected $request;
60
61
    /** @var Response|null */
62
    protected $response;
63
64
    /** @var ResourceInterface|null */
65
    protected $resource;
66
67
    /** @var array */
68
    protected $config;
69
70
    /**
71
     * Smokescreen constructor.
72
     *
73
     * @param \Rexlabs\Smokescreen\Smokescreen $smokescreen
74
     * @param array                            $config
75
     */
76
    public function __construct(\Rexlabs\Smokescreen\Smokescreen $smokescreen, array $config = [])
77
    {
78
        $this->smokescreen = $smokescreen;
79
        $this->config = $config;
80
    }
81
82
    /**
83
     * Creates a new Smokescreen object.
84
     *
85
     * @param \Rexlabs\Smokescreen\Smokescreen|null $smokescreen
86
     * @param array                                 $config
87
     *
88
     * @return static
89
     */
90
    public static function make(\Rexlabs\Smokescreen\Smokescreen $smokescreen = null, array $config = [])
91
    {
92
        return new static($smokescreen ?? new \Rexlabs\Smokescreen\Smokescreen(), $config);
93
    }
94
95
    /**
96
     * Set the resource (item or collection) data to be transformed.
97
     * You should pass in an instance of a Model.
98
     *
99
     * @param mixed|Model|array                  $data
100
     * @param callable|TransformerInterface|null $transformer
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $resourceKey is correct as it would always require null to be passed?
Loading history...
101
     * @param null                               $resourceKey
102
     *
103
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
104
     *
105
     * @return $this|\Illuminate\Contracts\Support\Responsable
106
     */
107
    public function transform($data, $transformer = null, $resourceKey = null)
0 ignored issues
show
Unused Code introduced by
The parameter $resourceKey is not used and could be removed. ( Ignorable by Annotation )

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

107
    public function transform($data, $transformer = null, /** @scrutinizer ignore-unused */ $resourceKey = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
108
    {
109
        switch ($this->determineResourceType($data)) {
110
            case self::TYPE_ITEM_RESOURCE:
111
                $this->item($data, $transformer);
112
                break;
113
            case self::TYPE_COLLECTION_RESOURCE:
114
                $this->collection($data, $transformer);
115
                break;
116
            default:
117
                $this->item($data, $transformer);
118
                break;
119
        }
120
121
        return $this;
122
    }
123
124
    /**
125
     * @param mixed $data
126
     *
127
     * @return string
128
     */
129
    public function determineResourceType($data): string
130
    {
131
        if ($data instanceof ItemResource) {
132
            // Explicitly declared itself as an Item
133
            return self::TYPE_ITEM_RESOURCE;
134
        }
135
136
        if ($data instanceof CollectionResource) {
137
            // Explicitly declared itself as a Collection
138
            return self::TYPE_COLLECTION_RESOURCE;
139
        }
140
141
        if ($data instanceof Model) {
142
            // Eloquent model treated as an item by default
143
            return self::TYPE_ITEM_RESOURCE;
144
        }
145
146
        if ($data instanceof Collection) {
147
            // Is an instance or extended class of Laravel Support\Collection
148
            return self::TYPE_COLLECTION_RESOURCE;
149
        }
150
151
        if ($data instanceof \Illuminate\Database\Eloquent\Builder || $data instanceof \Illuminate\Database\Query\Builder) {
152
            // Treat query builders as a collection
153
            return self::TYPE_COLLECTION_RESOURCE;
154
        }
155
156
        if ($data instanceof LengthAwarePaginator) {
157
            // Is an instance of Pagination
158
            return self::TYPE_COLLECTION_RESOURCE;
159
        }
160
161
        if ($data instanceof HasMany || $data instanceof HasManyThrough || $data instanceof BelongsToMany) {
162
            // Many relationships are treated as a collection
163
            return self::TYPE_COLLECTION_RESOURCE;
164
        }
165
166
        if ($data instanceof Arrayable) {
167
            // Get array data for Arrayable so that we can determine resource type
168
            $data = $data->toArray();
169
        }
170
171
        if (\is_array($data)) {
172
            // Handle plain arrays
173
            if (Arr::isAssoc($data)) {
174
                // Associative arrays are treated as items
175
                return self::TYPE_ITEM_RESOURCE;
176
            }
177
178
            // All other arrays are considered collections
179
            return self::TYPE_COLLECTION_RESOURCE;
180
        }
181
182
        // Everything else is ambiguous resource type
183
        return self::TYPE_AMBIGUOUS_RESOURCE;
184
    }
185
186
    /**
187
     * Set an item resource to be transformed.
188
     *
189
     * @param mixed                              $data
190
     * @param callable|TransformerInterface|null $transformer
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $resourceKey is correct as it would always require null to be passed?
Loading history...
191
     * @param null                               $resourceKey
192
     *
193
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
194
     *
195
     * @return $this|\Illuminate\Contracts\Support\Responsable
196
     */
197
    public function item($data, $transformer = null, $resourceKey = null)
198
    {
199
        $this->setResource(new Item($data, $transformer, $resourceKey));
200
201
        return $this;
202
    }
203
204
    /**
205
     * Set a collection resource to be transformed.
206
     *
207
     * @param mixed                              $data
208
     * @param callable|TransformerInterface|null $transformer
209
     *
210
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
211
     *
212
     * @return $this|\Illuminate\Contracts\Support\Responsable
213
     */
214
    public function collection($data, $transformer = null, $resourceKey = null)
215
    {
216
        $paginator = null;
217
218
        if ($data instanceof LengthAwarePaginator) {
219
            $paginator = $data;
220
            $data = $data->getCollection();
221
        } elseif ($data instanceof Relation) {
222
            $data = $data->get();
223
        } elseif ($data instanceof Builder) {
224
            $data = $data->get();
225
        } elseif ($data instanceof Model) {
226
            $data = new Collection([$data]);
227
        }
228
229
        // Create a new collection resource
230
        $resource = new \Rexlabs\Smokescreen\Resource\Collection($data, $transformer, $resourceKey);
231
        if ($paginator !== null) {
232
            // Assign any paginator to the resource
233
            $resource->setPaginator(new PaginatorBridge($paginator));
234
        }
235
        $this->setResource($resource);
236
237
        return $this;
238
    }
239
240
    /**
241
     * Set the transformer used to transform the resource(s).
242
     *
243
     * @param TransformerInterface|callable|null $transformer
244
     *
245
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
246
     *
247
     * @return $this|\Illuminate\Contracts\Support\Responsable
248
     */
249
    public function transformWith($transformer)
250
    {
251
        if ($this->resource === null) {
252
            throw new MissingResourceException('Cannot set transformer before setting resource');
253
        }
254
        $this->resource->setTransformer($transformer);
255
256
        return $this;
257
    }
258
259
    /**
260
     * Set the default serializer to be used for resources which do not have an explictly set serializer.
261
     *
262
     * @param SerializerInterface|null $serializer
263
     *
264
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
265
     *
266
     * @return $this|\Illuminate\Contracts\Support\Responsable
267
     */
268
    public function serializeWith($serializer)
269
    {
270
        $this->serializer = $serializer;
271
272
        return $this;
273
    }
274
275
    /**
276
     * Set the relationship loader.
277
     * The relationship loader takes the relationships defined on a transformer, and eager-loads them.
278
     *
279
     * @param RelationLoaderInterface $relationLoader
280
     *
281
     * @return $this|\Illuminate\Contracts\Support\Responsable
282
     */
283
    public function loadRelationsVia(RelationLoaderInterface $relationLoader)
284
    {
285
        $this->smokescreen->setRelationLoader($relationLoader);
286
287
        return $this;
288
    }
289
290
    /**
291
     * Returns an object representation of the transformed/serialized data.
292
     *
293
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
294
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
295
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
296
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
297
     *
298
     * @return \stdClass
299
     */
300
    public function toObject(): \stdClass
301
    {
302
        return json_decode($this->toJson(), false);
303
    }
304
305
    /**
306
     * Outputs a JSON string of the resulting transformed and serialized data.
307
     * Implements Laravel's Jsonable interface.
308
     *
309
     * @param int $options
310
     *
311
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
312
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
313
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
314
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
315
     *
316
     * @return string
317
     */
318
    public function toJson($options = 0): string
319
    {
320
        return JsonHelper::encode($this->jsonSerialize(), $options);
321
    }
322
323
    /**
324
     * Output the transformed and serialized data as an array.
325
     * Implements PHP's JsonSerializable interface.
326
     *
327
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
328
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
329
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
330
     *
331
     * @return array
332
     *
333
     * @see Smokescreen::toArray()
334
     */
335
    public function jsonSerialize(): array
336
    {
337
        return $this->toArray();
338
    }
339
340
    /**
341
     * Output the transformed and serialized data as an array.
342
     * This kicks off the transformation via the base Smokescreen object.
343
     *
344
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
345
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
346
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
347
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
348
     *
349
     * @return array
350
     */
351
    public function toArray(): array
352
    {
353
        // We must have a resource provided to transform.
354
        if ($this->resource === null) {
355
            throw new MissingResourceException('Resource is not defined');
356
        }
357
358
        // If there is no transformer assigned to the resource, we'll try find one.
359
        if (!$this->resource->hasTransformer()) {
360
            // Try to resolve one based on the underlying model (if any).
361
362
            $transformer = $this->resolveTransformerForResource($this->resource);
363
            $this->resource->setTransformer($transformer);
364
        }
365
366
        // Assign the resource in the base instance.
367
        $this->smokescreen->setResource($this->resource);
368
369
        // Serializer may be overridden via config
370
        // We may be setting the serializer to null, in which case a default will be provided.
371
        $serializer = $this->serializer ?? $this->config['default_serializer'] ?? null;
372
        $this->smokescreen->setSerializer($serializer);
373
374
        // Assign any includes.
375
        if ($this->includes) {
376
            // Includes have been set explicitly.
377
            $this->smokescreen->parseIncludes($this->includes);
378
        } elseif ($this->autoParseIncludes) {
379
            // If autoParseIncludes is not false, then try to parse from the request object.
380
            $this->smokescreen->parseIncludes($this->request()->input($this->getIncludeKey()));
0 ignored issues
show
Bug introduced by
It seems like $this->request()->input($this->getIncludeKey()) can also be of type array; however, parameter $str of Rexlabs\Smokescreen\Smokescreen::parseIncludes() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

380
            $this->smokescreen->parseIncludes(/** @scrutinizer ignore-type */ $this->request()->input($this->getIncludeKey()));
Loading history...
381
        } else {
382
            // Empty includes
383
            $this->smokescreen->parseIncludes('');
384
        }
385
386
        // We will provide the Laravel relationship loader if none has already
387
        // been explicitly defined.
388
        if (!$this->smokescreen->hasRelationLoader()) {
389
            $this->smokescreen->setRelationLoader(new RelationLoader());
390
        }
391
392
        // Kick off the transformation via the Smokescreen base library.
393
        return $this->smokescreen->toArray();
394
    }
395
396
    /**
397
     * Determines the Transformer object to be used for a particular resource.
398
     * Inspects the underlying Eloquent model to determine an appropriately
399
     * named transformer class, and instantiate the object.
400
     *
401
     * @param ResourceInterface $resource
402
     *
403
     * @throws UnresolvedTransformerException
404
     *
405
     * @return TransformerInterface|callable|null
406
     */
407
    protected function resolveTransformerForResource(ResourceInterface $resource)
408
    {
409
        $data = $resource->getData();
410
411
        // Find the underlying model of the resource data
412
        $model = null;
413
        if ($data instanceof Model) {
414
            $model = $data;
415
        } elseif ($data instanceof Collection) {
416
            $model = $data->first();
417
        }
418
419
        // If no model can be determined from the data
420
        if ($model === null) {
421
            // Don't assign any transformer for this data
422
            return;
423
        }
424
425
        // Cool, now let's try to find a matching transformer based on our Model class
426
        // We use our configuration value 'transformer_namespace' to determine where to look.
427
        try {
428
            $transformerClass = sprintf('%s\\%sTransformer',
429
                $this->config['transformer_namespace'] ?? 'App\\Transformers',
430
                (new \ReflectionClass($model))->getShortName());
431
            $transformer = app()->make($transformerClass);
432
        } catch (\Exception $e) {
433
            throw new UnresolvedTransformerException('Unable to resolve transformer for model: '.\get_class($model), 0, $e);
434
        }
435
436
        return $transformer;
437
    }
438
439
    /**
440
     * Get a Laravel request object.  If not set explicitly via setRequest(...) then
441
     * it will be automatically resolved out of the container. You're welcome.
442
     *
443
     * @return \Illuminate\Http\Request
444
     */
445
    public function request(): Request
446
    {
447
        if ($this->request === null) {
448
            // Resolve request out of the container.
449
            $this->request = app('request');
450
        }
451
452
        return $this->request;
453
    }
454
455
    /**
456
     * Determine which key is used for the includes when passing from the Request
457
     * If the autoParseIncludes property is set to a string value this will be used
458
     * otherwise, the 'include_key' from the configuration.
459
     * Defaults to 'include'.
460
     *
461
     * @return string
462
     */
463
    public function getIncludeKey(): string
464
    {
465
        if (\is_string($this->autoParseIncludes)) {
466
            // When set to a string value, indicates the include key
467
            return $this->autoParseIncludes;
468
        }
469
470
        return $this->config['include_key'] ?? 'include';
471
    }
472
473
    /**
474
     * Generates a Response object.
475
     * Implements Laravel's Responsable contract, so that you can return smokescreen object from a controller.
476
     *
477
     * @param \Illuminate\Http\Request $request
478
     *
479
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
480
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
481
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
482
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
483
     *
484
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
485
     */
486
    public function toResponse($request)
487
    {
488
        return $this->response();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->response() returns the type Illuminate\Http\JsonResponse which is incompatible with the return type mandated by Illuminate\Contracts\Sup...sponsable::toResponse() of Illuminate\Http\Response.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
489
    }
490
491
    /**
492
     * Return a JsonResponse object containing the resolved/compiled JSON data.
493
     * Note, since the generated Response is cached, consecutive calls to response() will not change the
494
     * response based on the given parameters. You can use withResponse($callback) to easily modify the response,
495
     * or via $this->response()->setStatusCode() etc.
496
     *
497
     * @param int   $statusCode
498
     * @param array $headers
499
     * @param int   $options
500
     *
501
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
502
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
503
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
504
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
505
     *
506
     * @return \Illuminate\Http\JsonResponse
507
     *
508
     * @see Smokescreen::toArray()
509
     */
510
    public function response(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
511
    {
512
        // Response will only be generated once. use clearResponse() to clear.
513
        if ($this->response === null) {
514
            $this->response = new JsonResponse($this->toArray(), $statusCode, $headers, $options);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Illuminate\Http\Json...de, $headers, $options) of type Illuminate\Http\JsonResponse is incompatible with the declared type null|Illuminate\Http\Response of property $response.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
515
        }
516
517
        return $this->response;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->response could return the type Illuminate\Http\Response which is incompatible with the type-hinted return Illuminate\Http\JsonResponse. Consider adding an additional type-check to rule them out.
Loading history...
518
    }
519
520
    /**
521
     * Returns a fresh (uncached) response.
522
     * See the response() method.
523
     *
524
     * @param int   $statusCode
525
     * @param array $headers
526
     * @param int   $options
527
     *
528
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
529
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
530
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
531
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
532
     *
533
     * @return \Illuminate\Http\JsonResponse
534
     *
535
     * @see Smokescreen::toArray()
536
     * @see Smokescreen::response()
537
     */
538
    public function freshResponse(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
539
    {
540
        $this->clearResponse();
541
542
        return $this->response($statusCode, $headers, $options);
543
    }
544
545
    /**
546
     * Clear the cached response object.
547
     *
548
     * @return $this|\Illuminate\Contracts\Support\Responsable
549
     */
550
    public function clearResponse()
551
    {
552
        $this->response = null;
553
554
        return $this;
555
    }
556
557
    /**
558
     * Apply a callback to the response.  The response will be generated if it has not already been.
559
     *
560
     * @param callable $apply
561
     *
562
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
563
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
564
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
565
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
566
     *
567
     * @return $this|\Illuminate\Contracts\Support\Responsable
568
     */
569
    public function withResponse(callable $apply)
570
    {
571
        $apply($this->response());
572
573
        return $this;
574
    }
575
576
    /**
577
     * Set the include string.
578
     *
579
     * @param string|null $includes
580
     *
581
     * @return $this|\Illuminate\Contracts\Support\Responsable
582
     */
583
    public function include($includes)
584
    {
585
        $this->includes = $includes === null ? $includes : (string) $includes;
586
587
        return $this;
588
    }
589
590
    /**
591
     * Disable all includes.
592
     *
593
     * @return $this|\Illuminate\Contracts\Support\Responsable
594
     */
595
    public function noIncludes()
596
    {
597
        $this->includes = null;
598
        $this->autoParseIncludes = false;
599
600
        return $this;
601
    }
602
603
    /**
604
     * Set the Laravel request object which will be used to resolve parameters.
605
     *
606
     * @param \Illuminate\Http\Request $request
607
     *
608
     * @return $this|\Illuminate\Contracts\Support\Responsable
609
     */
610
    public function setRequest(Request $request)
611
    {
612
        $this->request = $request;
613
614
        return $this;
615
    }
616
617
    /**
618
     * @return null|ResourceInterface
619
     */
620
    public function getResource()
621
    {
622
        return $this->resource;
623
    }
624
625
    /**
626
     * @param $resource null|ResourceInterface
627
     *
628
     * @return Smokescreen
629
     */
630
    public function setResource($resource)
631
    {
632
        $this->resource = $resource;
633
634
        // Clear any cached response when the resource changes
635
        $this->clearResponse();
636
637
        return $this;
638
    }
639
640
    /**
641
     * Get the underlying Smokescreen instance that we are wrapping in our laravel-friendly layer.
642
     *
643
     * @return \Rexlabs\Smokescreen\Smokescreen
644
     */
645
    public function getBaseSmokescreen(): \Rexlabs\Smokescreen\Smokescreen
646
    {
647
        return $this->smokescreen;
648
    }
649
}
650