Issues (17)

src/ApiResponse.php (4 issues)

1
<?php
2
3
namespace ElfSundae\Laravel\Api;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Http\JsonResponse;
7
use Illuminate\Database\Eloquent\Model;
8
9
class ApiResponse extends JsonResponse
10
{
11
    /**
12
     * The api result code.
13
     *
14
     * @var int
15
     */
16
    protected $code;
17
18
    /**
19
     * The keys which value should be clean.
20
     *
21
     * @var array|null
22
     */
23
    protected $cleanKeys;
24
25
    /**
26
     * Create an ApiResponse instance.
27
     *
28
     * @param  mixed  $data
29
     * @param  int|null  $code
30
     * @param  array  $headers
31
     * @param  int  $options
32
     */
33
    public function __construct($data = null, $code = null, $headers = [], $options = 0)
34
    {
35
        $this->code = is_null($code) ? static::successCode() : (int) $code;
36
37
        parent::__construct($data, 200, $headers, $options);
38
    }
39
40
    /**
41
     * Get the code key.
42
     *
43
     * @return string
44
     */
45
    public static function codeKey()
46
    {
47
        static $codeKey = null;
48
49
        if (is_null($codeKey)) {
50
            $codeKey = config('api.response.key.code', 'code');
0 ignored issues
show
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

50
            $codeKey = /** @scrutinizer ignore-call */ config('api.response.key.code', 'code');
Loading history...
51
        }
52
53
        return $codeKey;
54
    }
55
56
    /**
57
     * Get the message key.
58
     *
59
     * @return string
60
     */
61
    public static function messageKey()
62
    {
63
        static $messageKey = null;
64
65
        if (is_null($messageKey)) {
66
            $messageKey = config('api.response.key.message', 'msg');
0 ignored issues
show
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
            $messageKey = /** @scrutinizer ignore-call */ config('api.response.key.message', 'msg');
Loading history...
67
        }
68
69
        return $messageKey;
70
    }
71
72
    /**
73
     * Get the success code.
74
     *
75
     * @return int
76
     */
77
    public static function successCode()
78
    {
79
        static $successCode = null;
80
81
        if (is_null($successCode)) {
82
            $successCode = (int) config('api.response.code.success', 1);
0 ignored issues
show
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

82
            $successCode = (int) /** @scrutinizer ignore-call */ config('api.response.code.success', 1);
Loading history...
83
        }
84
85
        return $successCode;
86
    }
87
88
    /**
89
     * Sets the data to be sent as JSON.
90
     *
91
     * @param  mixed  $data
92
     * @return $this
93
     */
94
    public function setData($data = null)
95
    {
96
        if ($data instanceof Model) {
97
            $data = [snake_case(class_basename($data)) => $this->convertObjectToArray($data)];
98
        } elseif (is_object($data)) {
99
            $data = $this->convertObjectToArray($data);
100
        } elseif (is_null($data)) {
101
            $data = [];
102
        } elseif (is_string($data)) {
103
            $data = [static::messageKey() => $data];
104
        }
105
106
        if (! is_array($data)) {
107
            $data = [static::messageKey() => json_encode($data)];
108
        }
109
110
        if (! array_key_exists(static::codeKey(), $data)) {
111
            $data[static::codeKey()] = $this->getCode();
112
        }
113
114
        if (! is_null($this->cleanKeys)) {
115
            $data = $this->cleanArray($data, $this->cleanKeys);
116
        }
117
118
        return parent::setData($data);
119
    }
120
121
    /**
122
     * Convert an object to array.
123
     *
124
     * @param  mixed  $object
125
     * @return array
126
     */
127
    protected function convertObjectToArray($object)
128
    {
129
        if (method_exists($object, 'toArray')) {
130
            return $object->toArray();
131
        }
132
133
        return json_decode(json_encode($object, true), true);
0 ignored issues
show
true of type true is incompatible with the type integer expected by parameter $flags of json_encode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

133
        return json_decode(json_encode($object, /** @scrutinizer ignore-type */ true), true);
Loading history...
134
    }
135
136
    /**
137
     * Clean the given array.
138
     *
139
     * @param  array  $array
140
     * @param  array|null  $keys
141
     * @return array
142
     */
143
    protected function cleanArray($array, $keys = null)
144
    {
145
        $keys = $keys ?: array_keys($array);
146
147
        foreach ($keys as $key) {
148
            if (is_array($value = Arr::get($array, $key))) {
149
                Arr::set($array, $key, array_filter($value));
150
            }
151
        }
152
153
        return $array;
154
    }
155
156
    /**
157
     * Merge new data into the current data.
158
     *
159
     * @param  array  ...$data
160
     * @return $this
161
     */
162
    public function mergeData(array ...$data)
163
    {
164
        return $this->setData(array_replace($this->getData(true), ...$data));
165
    }
166
167
    /**
168
     * Get the api result code.
169
     *
170
     * @return int
171
     */
172
    public function getCode()
173
    {
174
        return $this->code;
175
    }
176
177
    /**
178
     * Set the api result code.
179
     *
180
     * @param  int  $code
181
     * @return $this
182
     */
183
    public function setCode($code)
184
    {
185
        $this->code = (int) $code;
186
187
        return $this->mergeData([static::codeKey() => $this->code]);
188
    }
189
190
    /**
191
     * Set the api result code.
192
     *
193
     * @param  int  $code
194
     * @return $this
195
     */
196
    public function code($code)
197
    {
198
        return $this->setCode($code);
199
    }
200
201
    /**
202
     * Get the api result message.
203
     *
204
     * @return string
205
     */
206
    public function getMessage()
207
    {
208
        return Arr::get($this->getData(true), static::messageKey());
209
    }
210
211
    /**
212
     * Set the api result message.
213
     *
214
     * @param  string  $message
215
     * @return $this
216
     */
217
    public function setMessage($message)
218
    {
219
        return $this->mergeData([static::messageKey() => (string) $message]);
220
    }
221
222
    /**
223
     * Set the api result message.
224
     *
225
     * @param  string  $message
226
     * @return $this
227
     */
228
    public function message($message)
229
    {
230
        return $this->setMessage($message);
231
    }
232
233
    /**
234
     * Get the keys which value should be clean.
235
     *
236
     * @return array|null
237
     */
238
    public function getCleanKeys()
239
    {
240
        return $this->cleanKeys;
241
    }
242
243
    /**
244
     * Set the keys which value should be clean, then clean data.
245
     * The passed $keys can be "dot" notation.
246
     *
247
     * $keys example:
248
     *
249
     * null             -> do not clean anything
250
     * []               -> clean values associated with all root keys
251
     * 'foo', 'foo.bar' -> clean values associated with 'foo' and 'foo'>'bar'
252
     * ['foo', 'foo.bar']
253
     *
254
     * @param  string|null|string[]  $keys
255
     * @return $this
256
     */
257
    public function clean($keys = [])
258
    {
259
        if (is_null($keys)) {
260
            $this->cleanKeys = null;
261
262
            return $this;
263
        }
264
265
        $this->cleanKeys = is_array($keys) ? $keys : func_get_args();
266
267
        return $this->setData($this->getData(true));
268
    }
269
270
    /**
271
     * Set the response status code.
272
     *
273
     * @param  int  $code
274
     * @param  mixed  $text
275
     * @return $this
276
     */
277
    public function statusCode($code, $text = null)
278
    {
279
        return $this->setStatusCode($code, $text);
280
    }
281
}
282