Passed
Push — master ( 9205c5...d0a6a4 )
by Lachlan
03:01
created

Smokescreen   F

Complexity

Total Complexity 67

Size/Duplication

Total Lines 663
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 150
dl 0
loc 663
ccs 165
cts 165
cp 1
rs 3.04
c 4
b 0
f 0
wmc 67

30 Methods

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