GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 8f00c6...366311 )
by Freek
10s
created

Fractal::create()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 8
nop 3
1
<?php
2
3
namespace Spatie\Fractalistic;
4
5
use Traversable;
6
use JsonSerializable;
7
use League\Fractal\Manager;
8
use League\Fractal\Pagination\CursorInterface;
9
use League\Fractal\Pagination\PaginatorInterface;
10
use League\Fractal\Serializer\SerializerAbstract;
11
use Spatie\Fractalistic\Exceptions\InvalidTransformation;
12
use Spatie\Fractalistic\Exceptions\NoTransformerSpecified;
13
14
class Fractal implements JsonSerializable
15
{
16
    /** @var \League\Fractal\Manager */
17
    protected $manager;
18
19
    /** @var int */
20
    protected $recursionLimit = 10;
21
22
    /** @var \League\Fractal\Serializer\SerializerAbstract */
23
    protected $serializer;
24
25
    /** @var \League\Fractal\TransformerAbstract|callable */
26
    protected $transformer;
27
28
    /** @var \League\Fractal\Pagination\PaginatorInterface */
29
    protected $paginator;
30
31
    /** @var \League\Fractal\Pagination\CursorInterface */
32
    protected $cursor;
33
34
    /** @var array */
35
    protected $includes = [];
36
37
    /** @var array */
38
    protected $excludes = [];
39
40
    /** @var array */
41
    protected $fieldsets = [];
42
43
    /** @var string */
44
    protected $dataType;
45
46
    /** @var mixed */
47
    protected $data;
48
49
    /** @var string */
50
    protected $resourceName;
51
52
    /** @var array */
53
    protected $meta = [];
54
55
    /**
56
     * @param null|mixed $data
57
     * @param null|callable|\League\Fractal\TransformerAbstract $transformer
58
     * @param null|\League\Fractal\Serializer\SerializerAbstract $serializer
59
     *
60
     * @return \Spatie\Fractalistic\Fractal
61
     */
62
    public static function create($data = null, $transformer = null, $serializer = null)
63
    {
64
        $instance = new static(new Manager());
65
66
        $instance->data = $data ?: null;
67
        $instance->dataType = $instance->determineDataType($data);
68
        $instance->transformer = $transformer ?: null;
69
        $instance->serializer = $serializer ?: null;
70
71
        return $instance;
72
    }
73
74
    /** @param \League\Fractal\Manager $manager */
75
    public function __construct(Manager $manager)
76
    {
77
        $this->manager = $manager;
78
    }
79
80
    /**
81
     * Set the collection data that must be transformed.
82
     *
83
     * @param mixed                                             $data
84
     * @param \League\Fractal\TransformerAbstract|callable|null $transformer
85
     * @param string|null                                       $resourceName
86
     *
87
     * @return $this
88
     */
89
    public function collection($data, $transformer = null, $resourceName = null)
90
    {
91
        $this->resourceName = $resourceName;
92
93
        return $this->data('collection', $data, $transformer);
94
    }
95
96
    /**
97
     * Set the item data that must be transformed.
98
     *
99
     * @param mixed                                             $data
100
     * @param \League\Fractal\TransformerAbstract|callable|null $transformer
101
     * @param string|null                                       $resourceName
102
     *
103
     * @return $this
104
     */
105
    public function item($data, $transformer = null, $resourceName = null)
106
    {
107
        $this->resourceName = $resourceName;
108
109
        return $this->data('item', $data, $transformer);
110
    }
111
112
    /**
113
     * Set the data that must be transformed.
114
     *
115
     * @param string                                            $dataType
116
     * @param mixed                                             $data
117
     * @param \League\Fractal\TransformerAbstract|callable|null $transformer
118
     *
119
     * @return $this
120
     */
121
    public function data($dataType, $data, $transformer = null)
122
    {
123
        $this->dataType = $dataType;
124
125
        $this->data = $data;
126
127
        if (! is_null($transformer)) {
128
            $this->transformer = $transformer;
129
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * @param mixed $data
136
     *
137
     * @return string
138
     */
139
    protected function determineDataType($data)
140
    {
141
        if (is_null($data)) {
142
            return 'NullResource';
143
        }
144
145
        if (is_array($data)) {
146
            return 'collection';
147
        }
148
149
        if ($data instanceof Traversable) {
150
            return 'collection';
151
        }
152
153
        return 'item';
154
    }
155
156
    /**
157
     * Set the class or function that will perform the transform.
158
     *
159
     * @param \League\Fractal\TransformerAbstract|callable $transformer
160
     *
161
     * @return $this
162
     */
163
    public function transformWith($transformer)
164
    {
165
        if (is_string($transformer) && class_exists($transformer)) {
166
            $transformer = new $transformer;
167
        }
168
169
        $this->transformer = $transformer;
170
171
        return $this;
172
    }
173
174
    /**
175
     * Set the serializer to be used.
176
     *
177
     * @param \League\Fractal\Serializer\SerializerAbstract $serializer
178
     *
179
     * @return $this
180
     */
181
    public function serializeWith(SerializerAbstract $serializer)
182
    {
183
        $this->serializer = $serializer;
184
185
        return $this;
186
    }
187
188
    /**
189
     * Set a Fractal paginator for the data.
190
     *
191
     * @param \League\Fractal\Pagination\PaginatorInterface $paginator
192
     *
193
     * @return $this
194
     */
195
    public function paginateWith(PaginatorInterface $paginator)
196
    {
197
        $this->paginator = $paginator;
198
199
        return $this;
200
    }
201
202
    /**
203
     * Set a Fractal cursor for the data.
204
     *
205
     * @param \League\Fractal\Pagination\CursorInterface $cursor
206
     *
207
     * @return $this
208
     */
209
    public function withCursor(CursorInterface $cursor)
210
    {
211
        $this->cursor = $cursor;
212
213
        return $this;
214
    }
215
216
    /**
217
     * Specify the includes.
218
     *
219
     * @param array|string $includes Array or string of resources to include.
220
     *
221
     * @return $this
222
     */
223
    public function parseIncludes($includes)
224
    {
225
        $includes = $this->normalizeIncludesOrExcludes($includes);
226
227
        $this->includes = array_merge($this->includes, (array) $includes);
228
229
        return $this;
230
    }
231
232
    /**
233
     * Specify the excludes.
234
     *
235
     * @param array|string $excludes Array or string of resources to exclude.
236
     * @return $this
237
     */
238
    public function parseExcludes($excludes)
239
    {
240
        $excludes = $this->normalizeIncludesOrExcludes($excludes);
241
242
        $this->excludes = array_merge($this->excludes, (array) $excludes);
243
244
        return $this;
245
    }
246
247
    /**
248
     * Specify the fieldsets to include in the response.
249
     *
250
     * @param array $fieldsets array with key = resourceName and value = fields to include
251
     *                                (array or comma separated string with field names)
252
     *
253
     * @return $this
254
     */
255
    public function parseFieldsets(array $fieldsets)
256
    {
257
        foreach ($fieldsets as $key => $fields) {
258
            if (is_array($fields)) {
259
                $fieldsets[$key] = implode(',', $fields);
260
            }
261
        }
262
263
        $this->fieldsets = array_merge($this->fieldsets, $fieldsets);
264
265
        return $this;
266
    }
267
268
    /**
269
     * Normalize the includes an excludes.
270
     *
271
     * @param array|string $includesOrExcludes
272
     *
273
     * @return array|string
274
     */
275
    protected function normalizeIncludesOrExcludes($includesOrExcludes = '')
276
    {
277
        if (! is_string($includesOrExcludes)) {
278
            return $includesOrExcludes;
279
        }
280
281
        return array_map(function ($value) {
282
            return trim($value);
283
        }, explode(',', $includesOrExcludes));
284
    }
285
286
    /**
287
     * Set the meta data.
288
     *
289
     * @param $array,...
290
     *
291
     * @return $this
292
     */
293
    public function addMeta()
294
    {
295
        foreach (func_get_args() as $meta) {
296
            if (is_array($meta)) {
297
                $this->meta += $meta;
298
            }
299
        }
300
301
        return $this;
302
    }
303
304
    /**
305
     * Set the resource name, to replace 'data' as the root of the collection or item.
306
     *
307
     * @param string $resourceName
308
     *
309
     * @return $this
310
     */
311
    public function withResourceName($resourceName)
312
    {
313
        $this->resourceName = $resourceName;
314
315
        return $this;
316
    }
317
318
    /**
319
     * Upper limit to how many levels of included data are allowed.
320
     *
321
     * @param int $recursionLimit
322
     *
323
     * @return $this
324
     */
325
    public function limitRecursion(int $recursionLimit)
326
    {
327
        $this->recursionLimit = $recursionLimit;
328
329
        return $this;
330
    }
331
332
    /**
333
     * Perform the transformation to json.
334
     *
335
     * @return string
336
     */
337
    public function toJson()
338
    {
339
        return $this->createData()->toJson();
340
    }
341
342
    /**
343
     * Perform the transformation to array.
344
     *
345
     * @return array
346
     */
347
    public function toArray()
348
    {
349
        return $this->createData()->toArray();
350
    }
351
352
    /**
353
     * Create fractal data.
354
     *
355
     * @return \League\Fractal\Scope
356
     *
357
     * @throws \Spatie\Fractalistic\Exceptions\InvalidTransformation
358
     * @throws \Spatie\Fractalistic\Exceptions\NoTransformerSpecified
359
     */
360
    public function createData()
361
    {
362
        if (is_null($this->transformer)) {
363
            throw new NoTransformerSpecified();
364
        }
365
366
        if (! is_null($this->serializer)) {
367
            $this->manager->setSerializer($this->serializer);
368
        }
369
370
        $this->manager->setRecursionLimit($this->recursionLimit);
371
372
        if (! empty($this->includes)) {
373
            $this->manager->parseIncludes($this->includes);
374
        }
375
376
        if (! empty($this->excludes)) {
377
            $this->manager->parseExcludes($this->excludes);
378
        }
379
380
        if (! empty($this->fieldsets)) {
381
            $this->manager->parseFieldsets($this->fieldsets);
382
        }
383
384
        return $this->manager->createData($this->getResource());
385
    }
386
387
    /**
388
     * Get the resource.
389
     *
390
     * @return \League\Fractal\Resource\ResourceInterface
391
     *
392
     * @throws \Spatie\Fractalistic\Exceptions\InvalidTransformation
393
     */
394
    public function getResource()
395
    {
396
        $resourceClass = 'League\\Fractal\\Resource\\'.ucfirst($this->dataType);
397
398
        if (! class_exists($resourceClass)) {
399
            throw new InvalidTransformation();
400
        }
401
402
        $resource = new $resourceClass($this->data, $this->transformer, $this->resourceName);
403
404
        $resource->setMeta($this->meta);
405
406
        if (! is_null($this->paginator)) {
407
            $resource->setPaginator($this->paginator);
408
        }
409
410
        if (! is_null($this->cursor)) {
411
            $resource->setCursor($this->cursor);
412
        }
413
414
        return $resource;
415
    }
416
417
    /**
418
     * Convert the object into something JSON serializable.
419
     */
420
    public function jsonSerialize()
421
    {
422
        return $this->toArray();
423
    }
424
425
    /**
426
     * Support for magic methods to included data.
427
     *
428
     * @param string $name
429
     * @param array  $arguments
430
     *
431
     * @return $this
432
     */
433
    public function __call($name, array $arguments)
434
    {
435 View Code Duplication
        if ($this->startsWith($name, ['include'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
436
            $includeName = lcfirst(substr($name, strlen('include')));
437
438
            return $this->parseIncludes($includeName);
439
        }
440
441 View Code Duplication
        if ($this->startsWith($name, ['exclude'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
442
            $excludeName = lcfirst(substr($name, strlen('exclude')));
443
444
            return $this->parseExcludes($excludeName);
445
        }
446
447
        trigger_error('Call to undefined method '.__CLASS__.'::'.$name.'()', E_USER_ERROR);
448
    }
449
450
    /**
451
     * Determine if a given string starts with a given substring.
452
     *
453
     * @param  string  $haystack
454
     * @param  string|array  $needles
455
     * @return bool
456
     */
457
    protected function startsWith($haystack, $needles)
458
    {
459
        foreach ((array) $needles as $needle) {
460
            if ($needle != '' && substr($haystack, 0, strlen($needle)) === (string) $needle) {
461
                return true;
462
            }
463
        }
464
465
        return false;
466
    }
467
}
468