This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php namespace Arcanedev\LaravelApiHelper\Http; |
||
2 | |||
3 | use ArrayAccess; |
||
4 | use Illuminate\Container\Container; |
||
5 | use Illuminate\Contracts\Routing\UrlRoutable; |
||
6 | use Illuminate\Contracts\Support\Arrayable; |
||
7 | use Illuminate\Contracts\Support\Responsable; |
||
8 | use Illuminate\Http\Resources\DelegatesToResource; |
||
9 | use Illuminate\Http\Resources\Json\PaginatedResourceResponse; |
||
10 | use Illuminate\Http\Resources\Json\ResourceResponse; |
||
11 | use Illuminate\Http\Resources\MergeValue; |
||
12 | use Illuminate\Http\Resources\MissingValue; |
||
13 | use Illuminate\Pagination\AbstractPaginator; |
||
14 | use Illuminate\Support\Arr; |
||
15 | use Illuminate\Support\Collection; |
||
16 | use JsonSerializable; |
||
17 | |||
18 | /** |
||
19 | * Class ApiResource |
||
20 | * |
||
21 | * @package Arcanedev\LaravelApiHelper\Http |
||
22 | * @author ARCANEDEV <[email protected]> |
||
23 | * |
||
24 | * @property mixed|null pivot |
||
25 | */ |
||
26 | class ApiResource implements ArrayAccess, JsonSerializable, Responsable, UrlRoutable |
||
27 | { |
||
28 | /* ----------------------------------------------------------------- |
||
29 | | Traits |
||
30 | | ----------------------------------------------------------------- |
||
31 | */ |
||
32 | |||
33 | use DelegatesToResource; |
||
34 | |||
35 | /* ----------------------------------------------------------------- |
||
36 | | Properties |
||
37 | | ----------------------------------------------------------------- |
||
38 | */ |
||
39 | |||
40 | /** |
||
41 | * The resource instance. |
||
42 | * |
||
43 | * @var mixed |
||
44 | */ |
||
45 | public $resource; |
||
46 | |||
47 | /** |
||
48 | * The additional data that should be added to the top-level resource array. |
||
49 | * |
||
50 | * @var array |
||
51 | */ |
||
52 | public $with = []; |
||
53 | |||
54 | /** |
||
55 | * The additional meta data that should be added to the resource response. |
||
56 | * |
||
57 | * Added during response construction by the developer. |
||
58 | * |
||
59 | * @var array |
||
60 | */ |
||
61 | public $additional = []; |
||
62 | |||
63 | /** |
||
64 | * The "data" wrapper that should be applied. |
||
65 | * |
||
66 | * @var string |
||
67 | */ |
||
68 | public static $wrap = 'data'; |
||
69 | |||
70 | /* ----------------------------------------------------------------- |
||
71 | | Constructor |
||
72 | | ----------------------------------------------------------------- |
||
73 | */ |
||
74 | |||
75 | /** |
||
76 | * PostTransformer constructor. |
||
77 | * |
||
78 | * @param mixed $resource |
||
79 | */ |
||
80 | 4 | public function __construct($resource) |
|
81 | { |
||
82 | 4 | $this->resource = $resource; |
|
83 | 4 | } |
|
84 | |||
85 | /** |
||
86 | * Create a new resource instance. |
||
87 | * |
||
88 | * @param mixed $resource |
||
89 | * |
||
90 | * @return static |
||
91 | */ |
||
92 | 4 | public static function make($resource) |
|
93 | { |
||
94 | 4 | return new static($resource); |
|
95 | } |
||
96 | |||
97 | /* ----------------------------------------------------------------- |
||
98 | | Main Methods |
||
99 | | ----------------------------------------------------------------- |
||
100 | */ |
||
101 | |||
102 | /** |
||
103 | * Transform the resource into an array. |
||
104 | * |
||
105 | * @param \Illuminate\Http\Request $request |
||
106 | * |
||
107 | * @return array |
||
108 | */ |
||
109 | public function toArray($request) |
||
110 | { |
||
111 | return $this->resource->toArray(); |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Get any additional data that should be returned with the resource array. |
||
116 | * |
||
117 | * @param \Illuminate\Http\Request $request |
||
118 | * |
||
119 | * @return array |
||
120 | */ |
||
121 | 4 | public function with($request) |
|
122 | { |
||
123 | 4 | return $this->with; |
|
124 | } |
||
125 | |||
126 | /** |
||
127 | * Add additional meta data to the resource response. |
||
128 | * |
||
129 | * @param array $data |
||
130 | * |
||
131 | * @return $this |
||
132 | */ |
||
133 | public function additional(array $data) |
||
134 | { |
||
135 | $this->additional = $data; |
||
136 | |||
137 | return $this; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Set the string that should wrap the outer-most resource array. |
||
142 | * |
||
143 | * @param string $value |
||
144 | */ |
||
145 | public static function wrap($value) |
||
146 | { |
||
147 | static::$wrap = $value; |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Disable wrapping of the outer-most resource array. |
||
152 | * |
||
153 | * @return void |
||
154 | */ |
||
155 | public static function withoutWrapping() |
||
156 | { |
||
157 | static::wrap(null); |
||
158 | } |
||
159 | |||
160 | |||
161 | /** |
||
162 | * Customize the response for a request. |
||
163 | * |
||
164 | * @param \Illuminate\Http\Request $request |
||
165 | * @param \Illuminate\Http\JsonResponse $response |
||
166 | * |
||
167 | * @return void |
||
168 | */ |
||
169 | 4 | public function withResponse($request, $response) |
|
170 | { |
||
171 | // |
||
172 | 4 | } |
|
173 | |||
174 | /** |
||
175 | * Merge the given attributes. |
||
176 | * |
||
177 | * @param array $attributes |
||
178 | * |
||
179 | * @return \Illuminate\Http\Resources\MergeValue |
||
180 | */ |
||
181 | protected function attributes($attributes) |
||
182 | { |
||
183 | return new MergeValue( |
||
184 | Arr::only($this->resource->toArray(), $attributes) |
||
185 | ); |
||
186 | } |
||
187 | |||
188 | /** |
||
189 | * Retrieve a relationship if it has been loaded. |
||
190 | * |
||
191 | * @param string $relationship |
||
192 | * |
||
193 | * @return \Illuminate\Http\Resources\MissingValue|mixed |
||
194 | */ |
||
195 | protected function whenLoaded($relationship) |
||
196 | { |
||
197 | return $this->resource->relationLoaded($relationship) |
||
198 | ? $this->resource->{$relationship} |
||
199 | : new MissingValue; |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * Execute a callback if the given pivot table has been loaded. |
||
204 | * |
||
205 | * @param string $table |
||
206 | * @param mixed $value |
||
207 | * @param mixed $default |
||
208 | * |
||
209 | * @return \Illuminate\Http\Resources\MissingValue|mixed |
||
210 | */ |
||
211 | protected function whenPivotLoaded($table, $value, $default = null) |
||
212 | { |
||
213 | if (func_num_args() === 2) |
||
214 | $default = new MissingValue; |
||
215 | |||
216 | return $this->when( |
||
217 | $this->pivot && ($this->pivot instanceof $table || $this->pivot->getTable() === $table), |
||
218 | ...[$value, $default] |
||
219 | ); |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Resolve the resource to an array. |
||
224 | * |
||
225 | * @param \Illuminate\Http\Request|null $request |
||
226 | * |
||
227 | * @return array |
||
228 | */ |
||
229 | 4 | public function resolve($request = null) |
|
230 | { |
||
231 | 4 | $request = $request ?: Container::getInstance()->make('request'); |
|
232 | |||
233 | 4 | if ($this->resource instanceof Collection) |
|
234 | $data = $this->resolveCollection($this->resource, $request); |
||
235 | 4 | elseif ($this->resource instanceof AbstractPaginator) |
|
236 | $data = $this->resolveCollection($this->resource->getCollection(), $request); |
||
237 | else |
||
238 | 4 | $data = $this->toArray($request); |
|
239 | |||
240 | 4 | if ($data instanceof Arrayable) |
|
241 | $data = $data->toArray(); |
||
242 | 3 | elseif ($data instanceof JsonSerializable) |
|
243 | $data = $data->jsonSerialize(); |
||
244 | |||
245 | 4 | return $this->resolveNestedRelations((array) $data, $request); |
|
246 | } |
||
247 | |||
248 | /** |
||
249 | * Resolve the nested resources to an array. |
||
250 | * |
||
251 | * @param array $data |
||
252 | * @param \Illuminate\Http\Request $request |
||
253 | * |
||
254 | * @return array |
||
255 | */ |
||
256 | 4 | protected function resolveNestedRelations($data, $request) |
|
257 | { |
||
258 | 4 | foreach ($data as $key => $value) { |
|
259 | 4 | if (is_array($value)) { |
|
260 | $data[$key] = $this->resolveNestedRelations($value, $request); |
||
261 | } |
||
262 | 3 | elseif ($value instanceof static) { |
|
263 | 1 | $data[$key] = $value->resolve($request); |
|
264 | } |
||
265 | } |
||
266 | |||
267 | 4 | return $this->filter($data); |
|
268 | } |
||
269 | |||
270 | /** |
||
271 | * Resolve the resource to an array. |
||
272 | * |
||
273 | * @param \Illuminate\Support\Collection $collection |
||
274 | * @param \Illuminate\Http\Request|null $request |
||
275 | * |
||
276 | * @return array |
||
277 | */ |
||
278 | public function resolveCollection($collection, $request = null) |
||
279 | { |
||
280 | return $collection->map(function ($item) use ($request) { |
||
281 | return (new static($item))->toArray($request); |
||
282 | })->all(); |
||
283 | } |
||
284 | |||
285 | /** |
||
286 | * Transform the resource into an HTTP response. |
||
287 | * |
||
288 | * @param \Illuminate\Http\Request|null $request |
||
289 | * |
||
290 | * @return \Illuminate\Http\Response |
||
291 | */ |
||
292 | 4 | public function response($request = null) |
|
293 | { |
||
294 | 4 | return $this->toResponse( |
|
295 | 4 | $request ?: Container::getInstance()->make('request') |
|
296 | ); |
||
297 | } |
||
298 | |||
299 | /** |
||
300 | * Create an HTTP response that represents the object. |
||
301 | * |
||
302 | * @param \Illuminate\Http\Request $request |
||
303 | * |
||
304 | * @return \Illuminate\Http\Response|mixed |
||
305 | */ |
||
306 | 4 | public function toResponse($request) |
|
307 | { |
||
308 | return ( |
||
0 ignored issues
–
show
|
|||
309 | 4 | $this->resource instanceof AbstractPaginator |
|
310 | ? new PaginatedResourceResponse($this) |
||
311 | 4 | : new ResourceResponse($this) |
|
312 | 4 | )->toResponse($request); |
|
313 | } |
||
314 | |||
315 | /** |
||
316 | * Retrieve a value based on a given condition. |
||
317 | * |
||
318 | * @param bool $condition |
||
319 | * @param mixed $value |
||
320 | * @param mixed $default |
||
321 | * |
||
322 | * @return \Illuminate\Http\Resources\MissingValue|mixed |
||
323 | */ |
||
324 | protected function when($condition, $value, $default = null) |
||
325 | { |
||
326 | return $condition |
||
327 | ? value($value) |
||
328 | : (func_num_args() === 3 ? value($default) : new MissingValue); |
||
329 | } |
||
330 | |||
331 | /** |
||
332 | * Filter the given data, removing any optional values. |
||
333 | * |
||
334 | * @param array $data |
||
335 | * |
||
336 | * @return array |
||
337 | */ |
||
338 | 4 | protected function filter($data) |
|
339 | { |
||
340 | 4 | $index = -1; |
|
341 | |||
342 | 4 | foreach ($data as $key => $value) { |
|
343 | 4 | $index++; |
|
344 | |||
345 | 4 | if (is_array($value)) { |
|
346 | $data[$key] = $this->filter($value); |
||
347 | |||
348 | continue; |
||
349 | } |
||
350 | |||
351 | 4 | if (is_numeric($key) && $value instanceof MergeValue) { |
|
352 | return $this->merge($data, $index, $this->filter($value->data)); |
||
353 | } |
||
354 | |||
355 | if ( |
||
356 | 4 | $value instanceof MissingValue || |
|
357 | 3 | ($value instanceof self && $value->resource instanceof MissingValue) |
|
358 | ) { |
||
359 | 1 | unset($data[$key]); |
|
360 | } |
||
361 | } |
||
362 | |||
363 | 4 | return $data; |
|
364 | } |
||
365 | |||
366 | /** |
||
367 | * Merge the given data in at the given index. |
||
368 | * |
||
369 | * @param array $data |
||
370 | * @param int $index |
||
371 | * @param array $merge |
||
372 | * |
||
373 | * @return array |
||
374 | */ |
||
375 | protected function merge($data, $index, $merge) |
||
376 | { |
||
377 | if (array_values($data) === $data) { |
||
378 | return array_merge( |
||
379 | array_merge(array_slice($data, 0, $index, true), $merge), |
||
380 | $this->filter(array_slice($data, $index + 1, null, true)) |
||
381 | ); |
||
382 | } |
||
383 | |||
384 | return array_slice($data, 0, $index, true) + |
||
385 | $merge + |
||
386 | $this->filter(array_slice($data, $index + 1, null, true)); |
||
387 | } |
||
388 | |||
389 | /** |
||
390 | * Merge a value based on a given condition. |
||
391 | * |
||
392 | * @param bool $condition |
||
393 | * @param mixed $value |
||
394 | * |
||
395 | * @return \Illuminate\Http\Resources\MissingValue|mixed |
||
396 | */ |
||
397 | protected function mergeWhen($condition, $value) |
||
398 | { |
||
399 | return $condition ? new MergeValue(value($value)) : new MissingValue; |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * Transform the given value if it is present. |
||
404 | * |
||
405 | * @param mixed $value |
||
406 | * @param callable $callback |
||
407 | * @param mixed $default |
||
408 | * |
||
409 | * @return mixed |
||
410 | */ |
||
411 | protected function transform($value, callable $callback, $default = null) |
||
412 | { |
||
413 | return transform( |
||
414 | $value, $callback, func_num_args() === 3 ? $default : new MissingValue |
||
415 | ); |
||
416 | } |
||
417 | |||
418 | /** |
||
419 | * Prepare the resource for JSON serialization. |
||
420 | * |
||
421 | * @return array |
||
422 | */ |
||
423 | public function jsonSerialize() |
||
424 | { |
||
425 | return $this->resolve(Container::getInstance()->make('request')); |
||
426 | } |
||
427 | } |
||
428 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.