Completed
Push — master ( 5deb42...23468b )
by Yaroslav
02:42
created

ApiResponse::__call()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 9.1448
c 0
b 0
f 0
cc 5
nc 7
nop 2
1
<?php
2
3
namespace Gcsc\LaravelApiResponse;
4
5
use HttpStatusCodes\RFCStatusCodes;
6
use Illuminate\Http\JsonResponse;
7
use Illuminate\Support\Str;
8
9
/**
10
 * Class ApiResponse.
11
 *
12
 * @method JsonResponse continue($data = [], string $message = null)
13
 * @method JsonResponse switchingProtocols($data = [], string $message = null)
14
 * @method JsonResponse processing($data = [], string $message = null)
15
 * @method JsonResponse ok($data = [], string $message = null)
16
 * @method JsonResponse created($data = [], string $message = null)
17
 * @method JsonResponse accepted($data = [], string $message = null)
18
 * @method JsonResponse nonAuthoritativeInformation($data = [], string $message = null)
19
 * @method JsonResponse noContent($data = [], string $message = null)
20
 * @method JsonResponse resetContent($data = [], string $message = null)
21
 * @method JsonResponse partialContent($data = [], string $message = null)
22
 * @method JsonResponse multiStatus($data = [], string $message = null)
23
 * @method JsonResponse alreadyReported($data = [], string $message = null)
24
 * @method JsonResponse imUsed($data = [], string $message = null)
25
 * @method JsonResponse multipleChoices($data = [], string $message = null)
26
 * @method JsonResponse movedPermanently($data = [], string $message = null)
27
 * @method JsonResponse found($data = [], string $message = null)
28
 * @method JsonResponse seeOther($data = [], string $message = null)
29
 * @method JsonResponse notModified($data = [], string $message = null)
30
 * @method JsonResponse useProxy($data = [], string $message = null)
31
 * @method JsonResponse reserved($data = [], string $message = null)
32
 * @method JsonResponse temporaryRedirect($data = [], string $message = null)
33
 * @method JsonResponse permanentRedirect($data = [], string $message = null)
34
 * @method JsonResponse badRequest($data = [], string $message = null)
35
 * @method JsonResponse unauthorized($data = [], string $message = null)
36
 * @method JsonResponse paymentRequired($data = [], string $message = null)
37
 * @method JsonResponse forbidden($data = [], string $message = null)
38
 * @method JsonResponse notFound($data = [], string $message = null)
39
 * @method JsonResponse methodNotAllowed($data = [], string $message = null)
40
 * @method JsonResponse notAcceptable($data = [], string $message = null)
41
 * @method JsonResponse proxyAuthenticationRequired($data = [], string $message = null)
42
 * @method JsonResponse requestTimeout($data = [], string $message = null)
43
 * @method JsonResponse conflict($data = [], string $message = null)
44
 * @method JsonResponse gone($data = [], string $message = null)
45
 * @method JsonResponse lengthRequired($data = [], string $message = null)
46
 * @method JsonResponse preconditionFailed($data = [], string $message = null)
47
 * @method JsonResponse payloadTooLarge($data = [], string $message = null)
48
 * @method JsonResponse uriTooLong($data = [], string $message = null)
49
 * @method JsonResponse unsupportedMediaType($data = [], string $message = null)
50
 * @method JsonResponse rangeNotSatisfiable($data = [], string $message = null)
51
 * @method JsonResponse expectationFailed($data = [], string $message = null)
52
 * @method JsonResponse imATeapot($data = [], string $message = null)
53
 * @method JsonResponse misdirectedRequest($data = [], string $message = null)
54
 * @method JsonResponse unprocessableEntity($data = [], string $message = null)
55
 * @method JsonResponse locked($data = [], string $message = null)
56
 * @method JsonResponse failedDependency($data = [], string $message = null)
57
 * @method JsonResponse tooEarly($data = [], string $message = null)
58
 * @method JsonResponse upgradeRequired($data = [], string $message = null)
59
 * @method JsonResponse preconditionRequired($data = [], string $message = null)
60
 * @method JsonResponse tooManyRequests($data = [], string $message = null)
61
 * @method JsonResponse requestHeaderFieldsTooLarge($data = [], string $message = null)
62
 * @method JsonResponse unavailableForLegalReasons($data = [], string $message = null)
63
 * @method JsonResponse internalServerError($data = [], string $message = null)
64
 * @method JsonResponse notImplemented($data = [], string $message = null)
65
 * @method JsonResponse badGateway($data = [], string $message = null)
66
 * @method JsonResponse serviceUnavailable($data = [], string $message = null)
67
 * @method JsonResponse gatewayTimeout($data = [], string $message = null)
68
 * @method JsonResponse versionNotSupported($data = [], string $message = null)
69
 * @method JsonResponse variantAlsoNegotiates($data = [], string $message = null)
70
 * @method JsonResponse insufficientStorage($data = [], string $message = null)
71
 * @method JsonResponse loopDetected($data = [], string $message = null)
72
 * @method JsonResponse notExtended($data = [], string $message = null)
73
 * @method JsonResponse networkAuthenticationRequired($data = [], string $message = null)
74
 */
75
class ApiResponse
76
{
77
    /* Default Response Content */
78
    protected $code = RFCStatusCodes::HTTP_OK;
79
    protected $message = '';
80
    protected $data = [];
81
    protected $meta = [];
82
    protected $headers = [];
83
    protected $options = 0;
84
85
    /* Response Configuration */
86
    protected $includeMessage = true;
87
    protected $messageKey = 'message';
88
    protected $includeMeta = true;
89
    protected $metaKey = 'meta';
90
    protected $defaultMeta = null;
91
    protected $dataOnTopLevel = false;
92
    protected $dataKey = 'data';
93
    protected $statusCodesClass = RFCStatusCodes::class;
94
95
    /**
96
     * Create a new ApiResponse Instance.
97
     * @param array $options
98
     */
99
    public function __construct(array $options = [])
100
    {
101
        foreach ($options as $optionKey => $option) {
102
            if (method_exists($this, Str::camel($optionKey))) {
103
                $this->${Str::camel($optionKey)}($option);
104
            }
105
        }
106
107
        $this->meta = $this->generateDefaultMeta();
108
    }
109
110
    public function __call($name, $arguments)
111
    {
112
        if (defined($this->statusCodesClass . '::HTTP_' . Str::upper(Str::snake($name)))) {
113
            $code = (int)constant($this->statusCodesClass . '::HTTP_' . Str::upper(Str::snake($name)));
114
            // $data
115
            if (!isset($arguments[0])) {
116
                $data = null;
117
            } else {
118
                $data = $arguments[0];
119
            }
120
121
            // $message
122
            if (!isset($arguments[1])) {
123
                $manager = new \HttpStatusCodes\StatusCodeManager();
124
                $statusCode = $manager->makeStatusCode($code);
125
                $message = $statusCode->getMessage();
126
            } else if (!is_string($arguments[1])) {
127
                throw new \InvalidArgumentException('Message should type of string');
128
            } else {
129
                $message = $arguments[1];
130
            }
131
132
            $this->message = $message;
133
134
            return call_user_func_array([$this, 'send'], [$data, $code]);
135
        }
136
137
        throw new \BadMethodCallException('Static method: "' . $name . '" not exists');
138
    }
139
140
    protected function generateDefaultMeta()
141
    {
142
        if (is_array($this->defaultMeta)) {
143
            return $this->defaultMeta;
144
        }
145
146
        if (is_callable($this->defaultMeta)) {
147
            return (array)($this->defaultMeta)();
148
        }
149
150
        return [
151
            'version'     => env('API_VERSION', config('laravel-api-response.api_version', '0')),
152
            'environment' => app()->environment(),
153
        ];
154
    }
155
156
    /**
157
     * @param mixed $data
158
     * @param int|null $code
159
     * @return \Illuminate\Http\JsonResponse
160
     */
161
    public function send($data = null, ?int $code = null): JsonResponse
162
    {
163
        if ($data) {
164
            $this->setData($data);
165
        }
166
        if ($code) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $code of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
167
            $this->setCode($code);
168
        }
169
170
        $responseData = [];
171
172
        if ($this->dataOnTopLevel) {
173
            $responseData = $this->data;
174
        } else {
175
            $responseData[$this->dataKey] = $this->data;
176
        }
177
178
        if ($this->includeMeta) {
179
            $responseData[$this->metaKey] = $this->meta;
180
        }
181
182
        if ($this->includeMessage) {
183
            $responseData[$this->messageKey] = $this->message;
184
        }
185
186
        return response()->json(
187
            $responseData,
188
            $this->code,
189
            $this->headers,
190
            $this->options
191
        );
192
    }
193
194
    /*
195
     *  * * * * * * * * * * * * * *
196
     *  Configure response
197
     *  * * * * * * * * * * * * * *
198
     * */
199
200
    public function includeMessage($includeMessage)
201
    {
202
        $this->includeMessage = (bool)$includeMessage;
203
204
        return $this;
205
    }
206
207
    public function messageKey(string $messageKey)
208
    {
209
        $this->messageKey = $messageKey;
210
211
        return $this;
212
    }
213
214
    public function includeMeta($includeMeta)
215
    {
216
        $this->includeMeta = (bool)$includeMeta;
217
218
        return $this;
219
    }
220
221
    public function metaKey(string $metaKey)
222
    {
223
        $this->metaKey = $metaKey;
224
225
        return $this;
226
    }
227
228
    public function defaultMeta($defaultMeta)
229
    {
230
        $this->defaultMeta = $defaultMeta;
231
232
        return $this;
233
    }
234
235
    public function dataOnTopLevel($dataOnTopLevel)
236
    {
237
        $this->dataOnTopLevel = (bool)$dataOnTopLevel;
238
239
        return $this;
240
    }
241
242
    public function dataKey(string $dataKey)
243
    {
244
        $this->dataKey = $dataKey;
245
246
        return $this;
247
    }
248
249
    public function statusCodesClass(string $statusCodesClass)
250
    {
251
        $this->statusCodesClass = $statusCodesClass;
252
253
        return $this;
254
    }
255
256
    /*
257
     *  * * * * * * * * * * * * * *
258
     *  Response data
259
     *  * * * * * * * * * * * * * *
260
     * */
261
262
    /**
263
     * @param int $code
264
     * @return ApiResponse
265
     */
266
    public function setCode(int $code): self
267
    {
268
        $this->code = $code;
269
270
        return $this;
271
    }
272
273
    /**
274
     * @param string $message
275
     * @return ApiResponse
276
     */
277
    public function setMessage(string $message): self
278
    {
279
        $this->message = $message;
280
281
        return $this;
282
    }
283
284
    /**
285
     * @param mixed $data
286
     * @return ApiResponse
287
     */
288
    public function setData($data): self
289
    {
290
        if (is_array($data)) {
291
            $this->data = $data;
292
        } else if (is_object($data)) {
293
            if (is_subclass_of($data, 'Illuminate\Http\Resources\Json\JsonResource')) {
294
                $this->data = $data->toArray(request());
295
            } else {
296
                $this->data = (array)$data;
297
            }
298
        } else {
299
            $this->data = [$data];
300
        }
301
302
        return $this;
303
    }
304
305
    /**
306
     * @param array $meta
307
     * @param bool $withoutDefault
308
     * @return self
309
     */
310
    public function setMeta(array $meta, bool $withoutDefault = false): self
311
    {
312
        if ($withoutDefault) {
313
            $this->meta = $meta;
314
        } else {
315
            $this->meta = array_merge($this->generateDefaultMeta(), $meta);
316
        }
317
318
        return $this;
319
    }
320
321
    /**
322
     * @param array $headers
323
     * @return self
324
     */
325
    public function setHeaders(array $headers): self
326
    {
327
        $this->headers = $headers;
328
329
        return $this;
330
    }
331
332
    /**
333
     * @param mixed $options
334
     * @return self
335
     */
336
    public function setOptions($options): self
337
    {
338
        $this->options = $options;
339
340
        return $this;
341
    }
342
}
343