1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Flugg\Responder; |
4
|
|
|
|
5
|
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator as Paginator; |
6
|
|
|
use Illuminate\Database\Eloquent\Builder; |
7
|
|
|
use Illuminate\Database\Eloquent\Model; |
8
|
|
|
use Illuminate\Database\Eloquent\Relations\Pivot; |
9
|
|
|
use Illuminate\Database\Eloquent\Relations\Relation; |
10
|
|
|
use Illuminate\Support\Collection; |
11
|
|
|
use InvalidArgumentException; |
12
|
|
|
use League\Fractal\Pagination\IlluminatePaginatorAdapter; |
13
|
|
|
use League\Fractal\Resource\Collection as CollectionResource; |
14
|
|
|
use League\Fractal\Resource\Item as ItemResource; |
15
|
|
|
use League\Fractal\Resource\NullResource; |
16
|
|
|
use League\Fractal\Resource\ResourceInterface; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* This class builds an instance of [\League\Fractal\Resource\ResourceInterface]. It |
20
|
|
|
* supports a variety of different types of data, and resolves the correct resource |
21
|
|
|
* automatically. |
22
|
|
|
* |
23
|
|
|
* @package flugger/laravel-responder |
24
|
|
|
* @author Alexander Tømmerås <[email protected]> |
25
|
|
|
* @license The MIT License |
26
|
|
|
*/ |
27
|
|
|
class ResourceFactory |
28
|
|
|
{ |
29
|
|
|
/** |
30
|
|
|
* Mappings of supported data types with corresponding make methods. |
31
|
|
|
* |
32
|
|
|
* @var array |
33
|
|
|
*/ |
34
|
|
|
const MAKE_METHODS = [ |
35
|
|
|
Builder::class => 'makeFromBuilder', |
36
|
|
|
Collection::class => 'makeFromCollection', |
37
|
|
|
Pivot::class => 'makeFromPivot', |
38
|
|
|
Model::class => 'makeFromModel', |
39
|
|
|
Paginator::class => 'makeFromPaginator', |
40
|
|
|
Relation::class => 'makeFromRelation' |
41
|
|
|
]; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Build a resource instance from the given data. |
45
|
|
|
* |
46
|
|
|
* @param mixed|null $data |
47
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
48
|
|
|
*/ |
49
|
|
|
public function make($data = null) |
50
|
|
|
{ |
51
|
|
|
if (is_null($data)) { |
52
|
|
|
return new NullResource(); |
53
|
|
|
} elseif (is_array($data)) { |
54
|
|
|
return static::makeFromArray($data); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
$method = static::getMakeMethod($data); |
58
|
|
|
|
59
|
|
|
return static::$method($data); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Resolve which make method to call from the given date type. |
64
|
|
|
* |
65
|
|
|
* @param mixed $data |
66
|
|
|
* @return string |
67
|
|
|
* @throws \InvalidArgumentException |
68
|
|
|
*/ |
69
|
|
|
protected function getMakeMethod($data):string |
70
|
|
|
{ |
71
|
|
|
foreach (static::MAKE_METHODS as $class => $method) { |
72
|
|
|
if ($data instanceof $class) { |
73
|
|
|
return $method; |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
throw new InvalidArgumentException('Given data cannot be transformed.'); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Make resource from an Eloquent model. |
82
|
|
|
* |
83
|
|
|
* @param \Illuminate\Database\Eloquent\Model $model |
84
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
85
|
|
|
*/ |
86
|
|
|
protected function makeFromModel(Model $model):ResourceInterface |
87
|
|
|
{ |
88
|
|
|
return new ItemResource($model); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Make resource from a collection of Eloquent models. |
93
|
|
|
* |
94
|
|
|
* @param array $array |
95
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
96
|
|
|
*/ |
97
|
|
|
protected function makeFromArray(array $array):ResourceInterface |
98
|
|
|
{ |
99
|
|
|
return empty($array) ? new NullResource() : new CollectionResource($array); |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Make resource from a collection. |
104
|
|
|
* |
105
|
|
|
* @param \Illuminate\Support\Collection $collection |
106
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
107
|
|
|
*/ |
108
|
|
|
protected function makeFromCollection(Collection $collection):ResourceInterface |
109
|
|
|
{ |
110
|
|
|
return static::makeFromArray($collection->all()); |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Make resource from an Eloquent query builder. |
115
|
|
|
* |
116
|
|
|
* @param \Illuminate\Database\Eloquent\Builder $query |
117
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
118
|
|
|
*/ |
119
|
|
|
protected function makeFromBuilder(Builder $query):ResourceInterface |
120
|
|
|
{ |
121
|
|
|
return static::makeFromCollection($query->get()); |
|
|
|
|
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Make resource from an Eloquent paginator. |
126
|
|
|
* |
127
|
|
|
* @param \Illuminate\Contracts\Pagination\LengthAwarePaginator $paginator |
128
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
129
|
|
|
*/ |
130
|
|
|
protected function makeFromPaginator(Paginator $paginator):ResourceInterface |
131
|
|
|
{ |
132
|
|
|
$resource = static::makeFromCollection($paginator->getCollection()); |
133
|
|
|
|
134
|
|
|
if ($resource instanceof CollectionResource) { |
135
|
|
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
return $resource; |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Make resource from an Eloquent pivot table. |
143
|
|
|
* |
144
|
|
|
* @param \Illuminate\Database\Eloquent\Relations\Pivot $pivot |
145
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
146
|
|
|
*/ |
147
|
|
|
protected function makeFromPivot(Pivot $pivot):ResourceInterface |
148
|
|
|
{ |
149
|
|
|
return static::makeFromModel($pivot); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* Make resource from an Eloquent query builder. |
154
|
|
|
* |
155
|
|
|
* @param \Illuminate\Database\Eloquent\Relations\Relation $relation |
156
|
|
|
* @return \League\Fractal\Resource\ResourceInterface |
157
|
|
|
*/ |
158
|
|
|
protected function makeFromRelation(Relation $relation):ResourceInterface |
159
|
|
|
{ |
160
|
|
|
return static::makeFromCollection($relation->get()); |
161
|
|
|
} |
162
|
|
|
} |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.