Completed
Pull Request — master (#12)
by Jodie
03:26
created

Smokescreen   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 627
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 63
dl 0
loc 627
rs 3.4609
c 0
b 0
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A toObject() 0 3 1
A toJson() 0 3 1
B collection() 0 24 6
A item() 0 5 1
A make() 0 3 1
A loadRelationsVia() 0 5 1
C determineResourceType() 0 55 14
A resolveTransformerVia() 0 5 1
A jsonSerialize() 0 3 1
A transformWith() 0 8 2
A transform() 0 15 3
A serializeWith() 0 5 1
A getResource() 0 3 1
A include() 0 5 2
A getBaseSmokescreen() 0 3 1
A setRequest() 0 5 1
A setResource() 0 8 1
A noIncludes() 0 6 1
A getIncludeKey() 0 8 2
A inject() 0 5 1
A toResponse() 0 3 1
A request() 0 8 2
A withResponse() 0 5 1
A freshResponse() 0 5 1
A setConfig() 0 14 3
A response() 0 8 2
C toArray() 0 52 8
A clearResponse() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Smokescreen often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Smokescreen, and based on these observations, apply Extract Interface, too.

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\Pagination\Paginator as PaginatorBridge;
21
use Rexlabs\Laravel\Smokescreen\Relations\RelationLoader;
22
use Rexlabs\Laravel\Smokescreen\Resources\CollectionResource;
23
use Rexlabs\Laravel\Smokescreen\Resources\ItemResource;
24
use Rexlabs\Laravel\Smokescreen\Transformers\TransformerResolver;
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
use Rexlabs\Smokescreen\Transformer\TransformerResolverInterface;
33
34
/**
35
 * Smokescreen for Laravel.
36
 * Tightly integrates the rexlabs/smokescreen resource transformation library with the Laravel framework.
37
 *
38
 * @author    Jodie Dunlop <[email protected]>
39
 * @copyright Rex Software 2018
40
 */
41
class Smokescreen implements \JsonSerializable, Jsonable, Arrayable, Responsable
42
{
43
    const TYPE_ITEM_RESOURCE = 'item';
44
    const TYPE_COLLECTION_RESOURCE = 'collection';
45
    const TYPE_AMBIGUOUS_RESOURCE = 'ambiguous';
46
47
    /** @var \Rexlabs\Smokescreen\Smokescreen */
48
    protected $smokescreen;
49
50
    /** @var string|null */
51
    protected $includes;
52
53
    /** @var string|bool Whether includes should be parsed from a request key */
54
    protected $autoParseIncludes = true;
55
56
    /** @var SerializerInterface|null */
57
    protected $serializer;
58
59
    /** @var Request|null */
60
    protected $request;
61
62
    /** @var Response|null */
63
    protected $response;
64
65
    /** @var ResourceInterface|null */
66
    protected $resource;
67
68
    /** @var array */
69
    protected $config;
70
71
    /** @var array */
72
    protected $injections;
73
74
    /**
75
     * Smokescreen constructor.
76
     *
77
     * @param \Rexlabs\Smokescreen\Smokescreen $smokescreen
78
     * @param array                            $config
79
     */
80
    public function __construct(\Rexlabs\Smokescreen\Smokescreen $smokescreen, array $config = [])
81
    {
82
        $this->smokescreen = $smokescreen;
83
        $this->setConfig($config);
84
    }
85
86
    /**
87
     * Creates a new Smokescreen object.
88
     *
89
     * @param \Rexlabs\Smokescreen\Smokescreen|null $smokescreen
90
     * @param array                                 $config
91
     *
92
     * @return static
93
     */
94
    public static function make(\Rexlabs\Smokescreen\Smokescreen $smokescreen = null, array $config = [])
95
    {
96
        return new static($smokescreen ?? new \Rexlabs\Smokescreen\Smokescreen(), $config);
97
    }
98
99
    /**
100
     * Set the resource (item or collection) data to be transformed.
101
     * You should pass in an instance of a Model.
102
     *
103
     * @param mixed|Model|array                  $data
104
     * @param callable|TransformerInterface|null $transformer
105
     * @param string|null                        $resourceKey
106
     *
107
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
108
     *
109
     * @return $this|\Illuminate\Contracts\Support\Responsable
110
     */
111
    public function transform($data, $transformer = null, $resourceKey = null)
112
    {
113
        switch ($this->determineResourceType($data)) {
114
            case self::TYPE_ITEM_RESOURCE:
115
                $this->item($data, $transformer, $resourceKey);
116
                break;
117
            case self::TYPE_COLLECTION_RESOURCE:
118
                $this->collection($data, $transformer, $resourceKey);
119
                break;
120
            default:
121
                $this->item($data, $transformer, $resourceKey);
122
                break;
123
        }
124
125
        return $this;
126
    }
127
128
    /**
129
     * @param mixed $data
130
     *
131
     * @return string
132
     */
133
    public function determineResourceType($data): string
134
    {
135
        if ($data instanceof ItemResource) {
136
            // Explicitly declared itself as an Item
137
            return self::TYPE_ITEM_RESOURCE;
138
        }
139
140
        if ($data instanceof CollectionResource) {
141
            // Explicitly declared itself as a Collection
142
            return self::TYPE_COLLECTION_RESOURCE;
143
        }
144
145
        if ($data instanceof Model) {
146
            // Eloquent model treated as an item by default
147
            return self::TYPE_ITEM_RESOURCE;
148
        }
149
150
        if ($data instanceof Collection) {
151
            // Is an instance or extended class of Laravel Support\Collection
152
            return self::TYPE_COLLECTION_RESOURCE;
153
        }
154
155
        if ($data instanceof \Illuminate\Database\Eloquent\Builder || $data instanceof \Illuminate\Database\Query\Builder) {
156
            // Treat query builders as a collection
157
            return self::TYPE_COLLECTION_RESOURCE;
158
        }
159
160
        if ($data instanceof LengthAwarePaginator) {
161
            // Is an instance of Pagination
162
            return self::TYPE_COLLECTION_RESOURCE;
163
        }
164
165
        if ($data instanceof HasMany || $data instanceof HasManyThrough || $data instanceof BelongsToMany) {
166
            // Many relationships are treated as a collection
167
            return self::TYPE_COLLECTION_RESOURCE;
168
        }
169
170
        if ($data instanceof Arrayable) {
171
            // Get array data for Arrayable so that we can determine resource type
172
            $data = $data->toArray();
173
        }
174
175
        if (\is_array($data)) {
176
            // Handle plain arrays
177
            if (Arr::isAssoc($data)) {
178
                // Associative arrays are treated as items
179
                return self::TYPE_ITEM_RESOURCE;
180
            }
181
182
            // All other arrays are considered collections
183
            return self::TYPE_COLLECTION_RESOURCE;
184
        }
185
186
        // Everything else is ambiguous resource type
187
        return self::TYPE_AMBIGUOUS_RESOURCE;
188
    }
189
190
    /**
191
     * Set an item resource to be transformed.
192
     *
193
     * @param mixed                              $data
194
     * @param callable|TransformerInterface|null $transformer
195
     * @param string|null                        $resourceKey
196
     *
197
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
198
     *
199
     * @return $this|\Illuminate\Contracts\Support\Responsable
200
     */
201
    public function item($data, $transformer = null, $resourceKey = null)
202
    {
203
        $this->setResource(new Item($data, $transformer, $resourceKey));
204
205
        return $this;
206
    }
207
208
    /**
209
     * Set a collection resource to be transformed.
210
     *
211
     * @param mixed                              $data
212
     * @param callable|TransformerInterface|null $transformer
213
     * @param string|null                        $resourceKey
214
     *
215
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
216
     *
217
     * @return $this|\Illuminate\Contracts\Support\Responsable
218
     */
219
    public function collection($data, $transformer = null, $resourceKey = null)
220
    {
221
        $paginator = null;
222
223
        if ($data instanceof LengthAwarePaginator) {
224
            $paginator = $data;
225
            $data = $data->getCollection();
226
        } elseif ($data instanceof Relation) {
227
            $data = $data->get();
228
        } elseif ($data instanceof Builder) {
229
            $data = $data->get();
230
        } elseif ($data instanceof Model) {
231
            $data = new Collection([$data]);
232
        }
233
234
        // Create a new collection resource
235
        $resource = new \Rexlabs\Smokescreen\Resource\Collection($data, $transformer, $resourceKey);
236
        if ($paginator !== null) {
237
            // Assign any paginator to the resource
238
            $resource->setPaginator(new PaginatorBridge($paginator));
239
        }
240
        $this->setResource($resource);
241
242
        return $this;
243
    }
244
245
    /**
246
     * Set the transformer used to transform the resource(s).
247
     *
248
     * @param TransformerInterface|callable|null $transformer
249
     *
250
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
251
     *
252
     * @return $this|\Illuminate\Contracts\Support\Responsable
253
     */
254
    public function transformWith($transformer)
255
    {
256
        if ($this->resource === null) {
257
            throw new MissingResourceException('Cannot set transformer before setting resource');
258
        }
259
        $this->resource->setTransformer($transformer);
260
261
        return $this;
262
    }
263
264
    /**
265
     * Set the default serializer to be used for resources which do not have an explictly set serializer.
266
     *
267
     * @param SerializerInterface|null $serializer
268
     *
269
     * @return $this|\Illuminate\Contracts\Support\Responsable
270
     */
271
    public function serializeWith($serializer)
272
    {
273
        $this->serializer = $serializer;
274
275
        return $this;
276
    }
277
278
    /**
279
     * Set the relationship loader.
280
     * The relationship loader takes the relationships defined on a transformer, and eager-loads them.
281
     *
282
     * @param RelationLoaderInterface $relationLoader
283
     *
284
     * @return $this|\Illuminate\Contracts\Support\Responsable
285
     */
286
    public function loadRelationsVia(RelationLoaderInterface $relationLoader)
287
    {
288
        $this->smokescreen->setRelationLoader($relationLoader);
289
290
        return $this;
291
    }
292
293
    /**
294
     * Sets the resolver to be used for locating transformers for resources.
295
     *
296
     * @param TransformerResolverInterface $transformerResolver
297
     *
298
     * @return $this
299
     */
300
    public function resolveTransformerVia(TransformerResolverInterface $transformerResolver)
301
    {
302
        $this->smokescreen->setTransformerResolver($transformerResolver);
303
304
        return $this;
305
    }
306
307
    /**
308
     * Returns an object representation of the transformed/serialized data.
309
     *
310
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
311
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
312
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
313
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
314
     *
315
     * @return \stdClass
316
     */
317
    public function toObject(): \stdClass
318
    {
319
        return json_decode($this->toJson(), false);
320
    }
321
322
    /**
323
     * Outputs a JSON string of the resulting transformed and serialized data.
324
     * Implements Laravel's Jsonable interface.
325
     *
326
     * @param int $options
327
     *
328
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
329
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
330
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
331
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
332
     *
333
     * @return string
334
     */
335
    public function toJson($options = 0): string
336
    {
337
        return JsonHelper::encode($this->jsonSerialize(), $options);
338
    }
339
340
    /**
341
     * Output the transformed and serialized data as an array.
342
     * Implements PHP's JsonSerializable interface.
343
     *
344
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
345
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
346
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
347
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
348
     *
349
     * @return array
350
     *
351
     * @see Smokescreen::toArray()
352
     */
353
    public function jsonSerialize(): array
354
    {
355
        return $this->toArray();
356
    }
357
358
    /**
359
     * Inject some data into the payload under given key (supports dot-notation).
360
     * This method can be called multiple times.
361
     *
362
     * @param string $key
363
     * @param mixed  $data
364
     *
365
     * @return $this
366
     */
367
    public function inject($key, $data)
368
    {
369
        $this->injections[$key] = $data;
370
371
        return $this;
372
    }
373
374
    /**
375
     * Output the transformed and serialized data as an array.
376
     * This kicks off the transformation via the base Smokescreen object.
377
     *
378
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
379
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
380
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
381
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
382
     * @throws \Rexlabs\Smokescreen\Exception\IncludeException
383
     *
384
     * @return array
385
     */
386
    public function toArray(): array
387
    {
388
        // We must have a resource provided to transform.
389
        if ($this->resource === null) {
390
            throw new MissingResourceException('Resource is not defined');
391
        }
392
393
        // Assign the resource in the base instance.
394
        $this->smokescreen->setResource($this->resource);
395
396
        // Serializer may be overridden via config.
397
        // We may be setting the serializer to null, in which case a default
398
        // will be provided.
399
        $serializer = $this->serializer ?? null;
400
        $this->smokescreen->setSerializer($serializer);
401
402
        // Assign any includes.
403
        if ($this->includes) {
404
            // Includes have been set explicitly.
405
            $this->smokescreen->parseIncludes($this->includes);
406
        } elseif ($this->autoParseIncludes) {
407
            // If autoParseIncludes is not false, then try to parse from the
408
            // request object.
409
            $this->smokescreen->parseIncludes((string) $this->request()->input($this->getIncludeKey()));
410
        } else {
411
            // Empty includes
412
            $this->smokescreen->parseIncludes('');
413
        }
414
415
        // Provide a custom transformer resolver which can interrogate the
416
        // underlying model and attempt to resolve a transformer class.
417
        if ($this->smokescreen->getTransformerResolver() === null) {
418
            $this->smokescreen->setTransformerResolver(
419
                new TransformerResolver($this->config['transformer_namespace'] ?? 'App\\Transformers')
420
            );
421
        }
422
423
        // We will provide the Laravel relationship loader if none has already
424
        // been explicitly defined.
425
        if (!$this->smokescreen->hasRelationLoader()) {
426
            $this->smokescreen->setRelationLoader(new RelationLoader());
427
        }
428
429
        // Kick off the transformation via the Smokescreen base library.
430
        $data = $this->smokescreen->toArray();
431
        if (!empty($this->injections)) {
432
            foreach ($this->injections as $key => $inject) {
433
                Arr::set($data, $key, $inject);
434
            }
435
        }
436
437
        return $data;
438
    }
439
440
    /**
441
     * Get a Laravel request object.  If not set explicitly via setRequest(...) then
442
     * it will be automatically resolved out of the container. You're welcome.
443
     *
444
     * @return \Illuminate\Http\Request
445
     */
446
    public function request(): Request
447
    {
448
        if ($this->request === null) {
449
            // Resolve request out of the container.
450
            $this->request = app('request');
451
        }
452
453
        return $this->request;
454
    }
455
456
    /**
457
     * Determine which key is used for the includes when passing from the Request
458
     * If the autoParseIncludes property is set to a string value this will be used
459
     * otherwise, the 'include_key' from the configuration.
460
     * Defaults to 'include'.
461
     *
462
     * @return string
463
     */
464
    public function getIncludeKey(): string
465
    {
466
        if (\is_string($this->autoParseIncludes)) {
467
            // When set to a string value, indicates the include key
468
            return $this->autoParseIncludes;
469
        }
470
471
        return $this->config['include_key'] ?? 'include';
472
    }
473
474
    /**
475
     * Generates a Response object.
476
     * Implements Laravel's Responsable contract, so that you can return smokescreen object from a controller.
477
     *
478
     * @param \Illuminate\Http\Request $request
479
     *
480
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
481
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
482
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
483
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
484
     *
485
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
486
     */
487
    public function toResponse($request)
488
    {
489
        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...
490
    }
491
492
    /**
493
     * Return a JsonResponse object containing the resolved/compiled JSON data.
494
     * Note, since the generated Response is cached, consecutive calls to response() will not change the
495
     * response based on the given parameters. You can use withResponse($callback) to easily modify the response,
496
     * or via $this->response()->setStatusCode() etc.
497
     *
498
     * @param int   $statusCode
499
     * @param array $headers
500
     * @param int   $options
501
     *
502
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
503
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
504
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
505
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
506
     *
507
     * @return \Illuminate\Http\JsonResponse
508
     *
509
     * @see Smokescreen::toArray()
510
     */
511
    public function response(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
512
    {
513
        // Response will only be generated once. use clearResponse() to clear.
514
        if ($this->response === null) {
515
            $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...
516
        }
517
518
        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...
519
    }
520
521
    /**
522
     * Returns a fresh (uncached) response.
523
     * See the response() method.
524
     *
525
     * @param int   $statusCode
526
     * @param array $headers
527
     * @param int   $options
528
     *
529
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
530
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
531
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
532
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
533
     *
534
     * @return \Illuminate\Http\JsonResponse
535
     *
536
     * @see Smokescreen::toArray()
537
     * @see Smokescreen::response()
538
     */
539
    public function freshResponse(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
540
    {
541
        $this->clearResponse();
542
543
        return $this->response($statusCode, $headers, $options);
544
    }
545
546
    /**
547
     * Clear the cached response object.
548
     *
549
     * @return $this|\Illuminate\Contracts\Support\Responsable
550
     */
551
    public function clearResponse()
552
    {
553
        $this->response = null;
554
555
        return $this;
556
    }
557
558
    /**
559
     * Apply a callback to the response.  The response will be generated if it has not already been.
560
     *
561
     * @param callable $apply
562
     *
563
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
564
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
565
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
566
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
567
     *
568
     * @return $this|\Illuminate\Contracts\Support\Responsable
569
     */
570
    public function withResponse(callable $apply)
571
    {
572
        $apply($this->response());
573
574
        return $this;
575
    }
576
577
    /**
578
     * Set the include string.
579
     *
580
     * @param string|null $includes
581
     *
582
     * @return $this|\Illuminate\Contracts\Support\Responsable
583
     */
584
    public function include($includes)
585
    {
586
        $this->includes = $includes === null ? $includes : (string) $includes;
587
588
        return $this;
589
    }
590
591
    /**
592
     * Disable all includes.
593
     *
594
     * @return $this|\Illuminate\Contracts\Support\Responsable
595
     */
596
    public function noIncludes()
597
    {
598
        $this->includes = null;
599
        $this->autoParseIncludes = false;
600
601
        return $this;
602
    }
603
604
    /**
605
     * Set the Laravel request object which will be used to resolve parameters.
606
     *
607
     * @param \Illuminate\Http\Request $request
608
     *
609
     * @return $this|\Illuminate\Contracts\Support\Responsable
610
     */
611
    public function setRequest(Request $request)
612
    {
613
        $this->request = $request;
614
615
        return $this;
616
    }
617
618
    /**
619
     * @return null|ResourceInterface
620
     */
621
    public function getResource()
622
    {
623
        return $this->resource;
624
    }
625
626
    /**
627
     * @param $resource null|ResourceInterface
628
     *
629
     * @return Smokescreen
630
     */
631
    public function setResource($resource)
632
    {
633
        $this->resource = $resource;
634
635
        // Clear any cached response when the resource changes
636
        $this->clearResponse();
637
638
        return $this;
639
    }
640
641
    /**
642
     * Get the underlying Smokescreen instance that we are wrapping in our laravel-friendly layer.
643
     *
644
     * @return \Rexlabs\Smokescreen\Smokescreen
645
     */
646
    public function getBaseSmokescreen(): \Rexlabs\Smokescreen\Smokescreen
647
    {
648
        return $this->smokescreen;
649
    }
650
651
    /**
652
     * @param array $config
653
     */
654
    protected function setConfig(array $config)
655
    {
656
        if (!empty($config['default_serializer'])) {
657
            $serializer = $config['default_serializer'];
658
            if (\is_string($serializer)) {
659
                // Given serializer is expected to be a class path
660
                // Instantiate via the container
661
                $serializer = app()->make($serializer);
662
            }
663
            $this->serializeWith($serializer);
664
            unset($config['default_serializer']);
665
        }
666
667
        $this->config = $config;
668
    }
669
}
670