Test Failed
Push — master ( dda6a4...a4eeee )
by Jodie
03:58
created

Smokescreen::setRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 2
nc 1
nop 1
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->setConfig($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
101
     * @param string|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)
108
    {
109
        switch ($this->determineResourceType($data)) {
110
            case self::TYPE_ITEM_RESOURCE:
111
                $this->item($data, $transformer, $resourceKey);
112
                break;
113
            case self::TYPE_COLLECTION_RESOURCE:
114
                $this->collection($data, $transformer, $resourceKey);
115
                break;
116
            default:
117
                $this->item($data, $transformer, $resourceKey);
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
191
     * @param string|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
     * @param string|null                        $resourceKey
210
     *
211
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
212
     *
213
     * @return $this|\Illuminate\Contracts\Support\Responsable
214
     */
215
    public function collection($data, $transformer = null, $resourceKey = null)
216
    {
217
        $paginator = null;
218
219
        if ($data instanceof LengthAwarePaginator) {
220
            $paginator = $data;
221
            $data = $data->getCollection();
222
        } elseif ($data instanceof Relation) {
223
            $data = $data->get();
224
        } elseif ($data instanceof Builder) {
225
            $data = $data->get();
226
        } elseif ($data instanceof Model) {
227
            $data = new Collection([$data]);
228
        }
229
230
        // Create a new collection resource
231
        $resource = new \Rexlabs\Smokescreen\Resource\Collection($data, $transformer, $resourceKey);
232
        if ($paginator !== null) {
233
            // Assign any paginator to the resource
234
            $resource->setPaginator(new PaginatorBridge($paginator));
235
        }
236
        $this->setResource($resource);
237
238
        return $this;
239
    }
240
241
    /**
242
     * Set the transformer used to transform the resource(s).
243
     *
244
     * @param TransformerInterface|callable|null $transformer
245
     *
246
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
247
     *
248
     * @return $this|\Illuminate\Contracts\Support\Responsable
249
     */
250
    public function transformWith($transformer)
251
    {
252
        if ($this->resource === null) {
253
            throw new MissingResourceException('Cannot set transformer before setting resource');
254
        }
255
        $this->resource->setTransformer($transformer);
256
257
        return $this;
258
    }
259
260
    /**
261
     * Set the default serializer to be used for resources which do not have an explictly set serializer.
262
     *
263
     * @param SerializerInterface|null $serializer
264
     *
265
     * @return $this|\Illuminate\Contracts\Support\Responsable
266
     */
267
    public function serializeWith($serializer)
268
    {
269
        $this->serializer = $serializer;
270
271
        return $this;
272
    }
273
274
    /**
275
     * Set the relationship loader.
276
     * The relationship loader takes the relationships defined on a transformer, and eager-loads them.
277
     *
278
     * @param RelationLoaderInterface $relationLoader
279
     *
280
     * @return $this|\Illuminate\Contracts\Support\Responsable
281
     */
282
    public function loadRelationsVia(RelationLoaderInterface $relationLoader)
283
    {
284
        $this->smokescreen->setRelationLoader($relationLoader);
285
286
        return $this;
287
    }
288
289
    /**
290
     * Returns an object representation of the transformed/serialized data.
291
     *
292
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
293
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
294
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
295
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
296
     *
297
     * @return \stdClass
298
     */
299
    public function toObject(): \stdClass
300
    {
301
        return json_decode($this->toJson(), false);
302
    }
303
304
    /**
305
     * Outputs a JSON string of the resulting transformed and serialized data.
306
     * Implements Laravel's Jsonable interface.
307
     *
308
     * @param int $options
309
     *
310
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
311
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
312
     * @throws \Rexlabs\Smokescreen\Exception\JsonEncodeException
313
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
314
     *
315
     * @return string
316
     */
317
    public function toJson($options = 0): string
318
    {
319
        return JsonHelper::encode($this->jsonSerialize(), $options);
320
    }
321
322
    /**
323
     * Output the transformed and serialized data as an array.
324
     * Implements PHP's JsonSerializable interface.
325
     *
326
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
327
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
328
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
329
     *
330
     * @return array
331
     *
332
     * @see Smokescreen::toArray()
333
     */
334
    public function jsonSerialize(): array
335
    {
336
        return $this->toArray();
337
    }
338
339
    /**
340
     * Output the transformed and serialized data as an array.
341
     * This kicks off the transformation via the base Smokescreen object.
342
     *
343
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
344
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
345
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
346
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
347
     *
348
     * @return array
349
     */
350
    public function toArray(): array
351
    {
352
        // We must have a resource provided to transform.
353
        if ($this->resource === null) {
354
            throw new MissingResourceException('Resource is not defined');
355
        }
356
357
        // If there is no transformer assigned to the resource, we'll try find one.
358
        if (!$this->resource->hasTransformer()) {
359
            // Try to resolve one based on the underlying model (if any).
360
361
            $transformer = $this->resolveTransformerForResource($this->resource);
362
            $this->resource->setTransformer($transformer);
363
        }
364
365
        // Assign the resource in the base instance.
366
        $this->smokescreen->setResource($this->resource);
367
368
        // Serializer may be overridden via config
369
        // We may be setting the serializer to null, in which case a default will be provided.
370
        $serializer = $this->serializer ?? null;
371
        $this->smokescreen->setSerializer($serializer);
372
373
        // Assign any includes.
374
        if ($this->includes) {
375
            // Includes have been set explicitly.
376
            $this->smokescreen->parseIncludes($this->includes);
377
        } elseif ($this->autoParseIncludes) {
378
            // If autoParseIncludes is not false, then try to parse from the request object.
379
            $this->smokescreen->parseIncludes((string) $this->request()->input($this->getIncludeKey()));
380
        } else {
381
            // Empty includes
382
            $this->smokescreen->parseIncludes('');
383
        }
384
385
        // We will provide the Laravel relationship loader if none has already
386
        // been explicitly defined.
387
        if (!$this->smokescreen->hasRelationLoader()) {
388
            $this->smokescreen->setRelationLoader(new RelationLoader());
389
        }
390
391
        // Kick off the transformation via the Smokescreen base library.
392
        return $this->smokescreen->toArray();
393
    }
394
395
    /**
396
     * Determines the Transformer object to be used for a particular resource.
397
     * Inspects the underlying Eloquent model to determine an appropriately
398
     * named transformer class, and instantiate the object.
399
     *
400
     * @param ResourceInterface $resource
401
     *
402
     * @throws UnresolvedTransformerException
403
     *
404
     * @return TransformerInterface|callable|null
405
     */
406
    protected function resolveTransformerForResource(ResourceInterface $resource)
407
    {
408
        $data = $resource->getData();
409
410
        // Find the underlying model of the resource data
411
        $model = null;
412
        if ($data instanceof Model) {
413
            $model = $data;
414
        } elseif ($data instanceof Collection) {
415
            $model = $data->first();
416
        }
417
418
        // If no model can be determined from the data
419
        if ($model === null) {
420
            // Don't assign any transformer for this data
421
            return null;
422
        }
423
424
        // Cool, now let's try to find a matching transformer based on our Model class
425
        // We use our configuration value 'transformer_namespace' to determine where to look.
426
        try {
427
            $transformerClass = sprintf('%s\\%sTransformer',
428
                $this->config['transformer_namespace'] ?? 'App\\Transformers',
429
                (new \ReflectionClass($model))->getShortName());
430
            $transformer = app()->make($transformerClass);
431
        } catch (\Exception $e) {
432
            throw new UnresolvedTransformerException('Unable to resolve transformer for model: '.\get_class($model), 0, $e);
433
        }
434
435
        return $transformer;
436
    }
437
438
    /**
439
     * Get a Laravel request object.  If not set explicitly via setRequest(...) then
440
     * it will be automatically resolved out of the container. You're welcome.
441
     *
442
     * @return \Illuminate\Http\Request
443
     */
444
    public function request(): Request
445
    {
446
        if ($this->request === null) {
447
            // Resolve request out of the container.
448
            $this->request = app('request');
449
        }
450
451
        return $this->request;
452
    }
453
454
    /**
455
     * Determine which key is used for the includes when passing from the Request
456
     * If the autoParseIncludes property is set to a string value this will be used
457
     * otherwise, the 'include_key' from the configuration.
458
     * Defaults to 'include'.
459
     *
460
     * @return string
461
     */
462
    public function getIncludeKey(): string
463
    {
464
        if (\is_string($this->autoParseIncludes)) {
465
            // When set to a string value, indicates the include key
466
            return $this->autoParseIncludes;
467
        }
468
469
        return $this->config['include_key'] ?? 'include';
470
    }
471
472
    /**
473
     * Generates a Response object.
474
     * Implements Laravel's Responsable contract, so that you can return smokescreen object from a controller.
475
     *
476
     * @param \Illuminate\Http\Request $request
477
     *
478
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
479
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
480
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
481
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
482
     *
483
     * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
484
     */
485
    public function toResponse($request)
486
    {
487
        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...
488
    }
489
490
    /**
491
     * Return a JsonResponse object containing the resolved/compiled JSON data.
492
     * Note, since the generated Response is cached, consecutive calls to response() will not change the
493
     * response based on the given parameters. You can use withResponse($callback) to easily modify the response,
494
     * or via $this->response()->setStatusCode() etc.
495
     *
496
     * @param int   $statusCode
497
     * @param array $headers
498
     * @param int   $options
499
     *
500
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
501
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
502
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
503
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
504
     *
505
     * @return \Illuminate\Http\JsonResponse
506
     *
507
     * @see Smokescreen::toArray()
508
     */
509
    public function response(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
510
    {
511
        // Response will only be generated once. use clearResponse() to clear.
512
        if ($this->response === null) {
513
            $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...
514
        }
515
516
        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...
517
    }
518
519
    /**
520
     * Returns a fresh (uncached) response.
521
     * See the response() method.
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
     * @see Smokescreen::response()
536
     */
537
    public function freshResponse(int $statusCode = 200, array $headers = [], int $options = 0): JsonResponse
538
    {
539
        $this->clearResponse();
540
541
        return $this->response($statusCode, $headers, $options);
542
    }
543
544
    /**
545
     * Clear the cached response object.
546
     *
547
     * @return $this|\Illuminate\Contracts\Support\Responsable
548
     */
549
    public function clearResponse()
550
    {
551
        $this->response = null;
552
553
        return $this;
554
    }
555
556
    /**
557
     * Apply a callback to the response.  The response will be generated if it has not already been.
558
     *
559
     * @param callable $apply
560
     *
561
     * @throws \Rexlabs\Smokescreen\Exception\UnhandledResourceType
562
     * @throws \Rexlabs\Smokescreen\Exception\InvalidTransformerException
563
     * @throws \Rexlabs\Laravel\Smokescreen\Exceptions\UnresolvedTransformerException
564
     * @throws \Rexlabs\Smokescreen\Exception\MissingResourceException
565
     *
566
     * @return $this|\Illuminate\Contracts\Support\Responsable
567
     */
568
    public function withResponse(callable $apply)
569
    {
570
        $apply($this->response());
571
572
        return $this;
573
    }
574
575
    /**
576
     * Set the include string.
577
     *
578
     * @param string|null $includes
579
     *
580
     * @return $this|\Illuminate\Contracts\Support\Responsable
581
     */
582
    public function include($includes)
583
    {
584
        $this->includes = $includes === null ? $includes : (string) $includes;
585
586
        return $this;
587
    }
588
589
    /**
590
     * Disable all includes.
591
     *
592
     * @return $this|\Illuminate\Contracts\Support\Responsable
593
     */
594
    public function noIncludes()
595
    {
596
        $this->includes = null;
597
        $this->autoParseIncludes = false;
598
599
        return $this;
600
    }
601
602
    /**
603
     * Set the Laravel request object which will be used to resolve parameters.
604
     *
605
     * @param \Illuminate\Http\Request $request
606
     *
607
     * @return $this|\Illuminate\Contracts\Support\Responsable
608
     */
609
    public function setRequest(Request $request)
610
    {
611
        $this->request = $request;
612
613
        return $this;
614
    }
615
616
    /**
617
     * @return null|ResourceInterface
618
     */
619
    public function getResource()
620
    {
621
        return $this->resource;
622
    }
623
624
    /**
625
     * @param $resource null|ResourceInterface
626
     *
627
     * @return Smokescreen
628
     */
629
    public function setResource($resource)
630
    {
631
        $this->resource = $resource;
632
633
        // Clear any cached response when the resource changes
634
        $this->clearResponse();
635
636
        return $this;
637
    }
638
639
    /**
640
     * Get the underlying Smokescreen instance that we are wrapping in our laravel-friendly layer.
641
     *
642
     * @return \Rexlabs\Smokescreen\Smokescreen
643
     */
644
    public function getBaseSmokescreen(): \Rexlabs\Smokescreen\Smokescreen
645
    {
646
        return $this->smokescreen;
647
    }
648
649
    /**
650
     * @param array $config
651
     */
652
    protected function setConfig(array $config)
653
    {
654
        if (!empty($config['default_serializer'])) {
655
            $serializer = $config['default_serializer'];
656
            if (\is_string($serializer)) {
657
                // Given serializer is expected to be a class path
658
                // Instantiate via the container
659
                $serializer = app()->make($serializer);
660
            }
661
            $this->serializeWith($serializer);
662
            unset($config['default_serializer']);
663
        }
664
665
        $this->config = $config;
666
    }
667
}
668