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 ( 224d14...101308 )
by ignace
25:01
created

JSend::isFail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Carpediem\JSend;
4
5
use InvalidArgumentException;
6
use JsonSerializable;
7
use UnexpectedValueException;
8
9
/**
10
 * A Immutable Value Object Class to represent a JSend object
11
 */
12
class JSend implements JsonSerializable
13
{
14
    const STATUS_SUCCESS = 'success';
15
16
    const STATUS_ERROR = 'error';
17
18
    const STATUS_FAIL = 'fail';
19
20
    /**
21
     * JSend status
22
     *
23
     * @var string
24
     */
25
    protected $status;
26
27
    /**
28
     * JSend Data
29
     *
30
     * @var array
31
     */
32
    protected $data = [];
33
34
    /**
35
     * JSend Error Message
36
     *
37
     * @var string
38
     */
39
    protected $errorMessage = '';
40
41
    /**
42
     * JSend Error Code
43
     * @var int|null
44
     */
45
    protected $errorCode;
46
47
    /**
48
     * New Instance
49
     *
50
     * @param string $status
51
     * @param array  $data
52
     * @param string $errorMessage
53
     * @param int    $errorCode
54
     */
55
    public function __construct($status, array $data = null, $errorMessage = null, $errorCode = null)
56
    {
57
        $this->status = $this->filterStatus($status);
58
        $this->data = $data ?: [];
59
        $this->filterError($errorMessage, $errorCode);
60
    }
61
62
    /**
63
     * Filter and Validate the JSend Status
64
     *
65
     * @param string $status
66
     *
67
     * @throws UnexpectedValueException If the status value does not conform to JSend Spec.
68
     *
69
     * @return string
70
     */
71
    protected function filterStatus($status)
72
    {
73
        $res = [self::STATUS_SUCCESS => 1, self::STATUS_ERROR => 1, self::STATUS_FAIL => 1];
74
        if (isset($res[$status])) {
75
            return $status;
76
        }
77
78
        throw new UnexpectedValueException('The given status does not conform to Jsend specification');
79
    }
80
81
    /**
82
     * Filter and Validate the JSend Error properties
83
     *
84
     * @param string $errorMessage
85
     * @param int    $errorCode
86
     */
87
    protected function filterError($errorMessage, $errorCode)
88
    {
89
        if (self::STATUS_ERROR != $this->status) {
90
            return;
91
        }
92
93
        $this->errorMessage = $this->validateType('string', 'is_string', $errorMessage);
94
        if (!is_null($errorCode)) {
95
            $this->errorCode = $this->validateType('numeric', 'is_numeric', $errorCode);
96
        }
97
    }
98
99
    /**
100
     * Validate a Type
101
     *
102
     * @param string   $type
103
     * @param callable $func
104
     * @param mixed    $str
105
     *
106
     * @throws UnexpectedValueException If the data value does not conform to the specified type
107
     *
108
     * @return mixed
109
     */
110
    protected function validateType($type, callable $func, $str)
111
    {
112
        if ($func($str)) {
113
            return $str;
114
        }
115
116
        throw new UnexpectedValueException(sprintf(
117
            'Expected data to be a %s; received "%s"',
118
            $type,
119
            (is_object($str) ? get_class($str) : gettype($str))
120
        ));
121
    }
122
123
    /**
124
     * Returns the JSend status
125
     *
126
     * @return string
127
     */
128
    public function getStatus()
129
    {
130
        return $this->status;
131
    }
132
133
    /**
134
     * Returns the JSend data
135
     *
136
     * @return array
137
     */
138
    public function getData()
139
    {
140
        return $this->data;
141
    }
142
143
    /**
144
     * Returns the JSend error message
145
     *
146
     * @return string
147
     */
148
    public function getErrorMessage()
149
    {
150
        return $this->errorMessage;
151
    }
152
153
    /**
154
     * Returns the JSend error code
155
     *
156
     * @return int|null
157
     */
158
    public function getErrorCode()
159
    {
160
        return $this->errorCode;
161
    }
162
163
    /**
164
     * Returns true if the status is success
165
     *
166
     * @return bool
167
     */
168
    public function isSuccess()
169
    {
170
        return self::STATUS_SUCCESS === $this->status;
171
    }
172
173
    /**
174
     * Returns true if the status is fail
175
     *
176
     * @return bool
177
     */
178
    public function isFail()
179
    {
180
        return self::STATUS_FAIL === $this->status;
181
    }
182
183
    /**
184
     * Returns true if the status is error
185
     *
186
     * @return bool
187
     */
188
    public function isError()
189
    {
190
        return self::STATUS_ERROR === $this->status;
191
    }
192
193
    /**
194
     * Transcode the JSend object into an array
195
     *
196
     * @return array
197
     */
198
    public function toArray()
199
    {
200
        $arr = ['status' => $this->status, 'data' => $this->data ?: null];
201
        if (self::STATUS_ERROR !== $this->status) {
202
            return $arr;
203
        }
204
205
        $arr['message'] = $this->errorMessage;
206
        if (!is_null($this->errorCode)) {
207
            $arr['code'] = $this->errorCode;
208
        }
209
210
        if (is_null($arr['data'])) {
211
            unset($arr['data']);
212
        }
213
214
        return $arr;
215
    }
216
217
    /**
218
     * @inheritdoc
219
     */
220
    public function jsonSerialize()
221
    {
222
        return $this->toArray();
223
    }
224
225
    /**
226
     * @inheritdoc
227
     */
228
    public function __toString()
229
    {
230
        return json_encode($this, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
231
    }
232
233
    /**
234
     * Encode and Send the JSend object as an HTTP Response
235
     *
236
     * @param array $headers Optional headers to add to the response
237
     *
238
     * @return string
239
     */
240
    public function send(array $headers = [])
241
    {
242
        $headers = $this->filterHeaders($headers);
243
        $headers[] = 'Content-Type: application/json;charset=utf-8';
244
        foreach ($headers as $header) {
245
            header($header);
246
        }
247
        echo $this;
248
    }
249
250
    /**
251
     * Filter Submitted Headers
252
     *
253
     * @param array $headers a Collection of key/value headers
254
     *
255
     * @return array
256
     */
257
    protected function filterHeaders(array $headers)
258
    {
259
        $formattedHeaders = [];
260
        foreach ($headers as $name => $value) {
261
            $formattedHeaders[] = $this->validateHeaderName($name).': '.$this->validateHeaderValue($value);
262
        }
263
264
        return $formattedHeaders;
265
    }
266
267
    /**
268
     * Validate Header name
269
     *
270
     * @param string $name
271
     *
272
     * @throws InvalidArgumentException if the header name is invalid
273
     *
274
     * @return string
275
     */
276
    protected function validateHeaderName($name)
277
    {
278
        if (!preg_match('/^[a-zA-Z0-9\'`#$%&*+.^_|~!-]+$/', $name)) {
279
            throw new InvalidArgumentException('Invalid header name');
280
        }
281
282
        return $name;
283
    }
284
285
    /**
286
     * Validate Header value
287
     *
288
     * @param string $name
0 ignored issues
show
Bug introduced by
There is no parameter named $name. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
289
     *
290
     * @throws InvalidArgumentException if the header value is invalid
291
     *
292
     * @return string
293
     */
294
    protected function validateHeaderValue($value)
295
    {
296
        if (preg_match("#(?:(?:(?<!\r)\n)|(?:\r(?!\n))|(?:\r\n(?![ \t])))#", $value)
297
            || preg_match('/[^\x09\x0a\x0d\x20-\x7E\x80-\xFE]/', $value)
298
        ) {
299
            throw new InvalidArgumentException('Invalid header value');
300
        }
301
302
        return $value;
303
    }
304
305
    /**
306
     * Returns an instance with the specified status.
307
     *
308
     * This method MUST retain the state of the current instance, and return
309
     * an instance that contains the specified status.
310
     *
311
     * @param string $status The status to use with the new instance.
312
     *
313
     * @return static A new instance with the specified status.
314
     */
315
    public function withStatus($status)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
316
    {
317
        if ($status === $this->status) {
318
            return $this;
319
        }
320
321
        return new static($status, $this->data, $this->errorMessage, $this->errorCode);
322
    }
323
324
    /**
325
     * Returns an instance with the specified data.
326
     *
327
     * This method MUST retain the state of the current instance, and return
328
     * an instance that contains the specified data.
329
     *
330
     * @param array $data The data to use with the new instance.
331
     *
332
     * @return static A new instance with the specified data.
333
     */
334
    public function withData(array $data)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
335
    {
336
        if ($data === $this->data) {
337
            return $this;
338
        }
339
340
        return new static($this->status, $data, $this->errorMessage, $this->errorCode);
341
    }
342
343
    /**
344
     * Returns an instance with the specified error message and error code.
345
     *
346
     * This method MUST retain the state of the current instance, and return
347
     * an instance that contains the specified error message and error code.
348
     *
349
     * @param string   $errorMessage The error message to use with the new instance.
350
     * @param int|null $errorCode    The error code to use with the new instance.
351
     *
352
     * @return static A new instance with the specified status.
353
     */
354
    public function withError($errorMessage, $errorCode = null)
355
    {
356
        if ($errorMessage == $this->errorMessage && $errorCode == $this->errorCode) {
357
            return $this;
358
        }
359
360
        return new static($this->status, $this->data, $errorMessage, $errorCode);
361
    }
362
363
    /**
364
     * Returns a successful JSend object with the specified data
365
     *
366
     * @param array $data The data to use with the new instance.
367
     *
368
     * @return static A new succesful instance with the specified data.
369
     */
370
    public static function success(array $data = [])
371
    {
372
        return new static(static::STATUS_SUCCESS, $data);
373
    }
374
375
    /**
376
     * Returns a failed JSend object with the specified data
377
     *
378
     * @param array $data The data to use with the new instance.
379
     *
380
     * @return static A new failed instance with the specified data.
381
     */
382
    public static function fail(array $data = [])
383
    {
384
        return new static(static::STATUS_FAIL, $data);
385
    }
386
387
    /**
388
     * Returns a error JSend object with the specified error message and error code.
389
     *
390
     * @param string   $errorMessage The error message to use with the new instance.
391
     * @param int|null $errorCode    The error code to use with the new instance.
392
     * @param array    $data         The optional data to use with the new instance.
393
     *
394
     * @return static A new failed instance with the specified data.
395
     */
396
    public static function error($errorMessage, $errorCode = null, $data = null)
397
    {
398
        return new static(static::STATUS_ERROR, $data, $errorMessage, $errorCode);
399
    }
400
401
    /**
402
     * Returns a new instance from a JSON string
403
     *
404
     * @param string $json    The string being decoded
405
     * @param int    $depth   User specified recursion depth.
406
     * @param int    $options Bitmask of JSON decode options
407
     *
408
     * @throws InvalidArgumentException If the string can not be decode
409
     *
410
     * @return static
411
     */
412
    public static function createFromString($json, $depth = 512, $options = 0)
413
    {
414
        $raw = json_decode($json, true, $depth, $options);
415
        if (JSON_ERROR_NONE !== json_last_error()) {
416
            throw new InvalidArgumentException(sprintf(
417
                'Unable to decode JSON to array in %s: %s',
418
                __CLASS__,
419
                json_last_error_msg()
420
            ));
421
        }
422
423
        return static::createFromArray($raw);
424
    }
425
426
    /**
427
     * Returns a new instance from an array
428
     *
429
     * @param array $arr The array to build a new JSend object with
430
     *
431
     * @return static
432
     */
433
    public static function createFromArray(array $arr)
434
    {
435
        $defaultValues = ['status' => null, 'data' => null, 'message' => null, 'code' => null];
436
        $arr = array_replace($defaultValues, array_intersect_key($arr, $defaultValues));
437
438
        return new static($arr['status'], $arr['data'], $arr['message'], $arr['code']);
439
    }
440
}
441