NanoHttpStatus   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 16
dl 0
loc 186
rs 10
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A isRedirection() 0 3 2
A isServerError() 0 3 2
A extractFirstDigit() 0 3 1
A isInformational() 0 3 2
A __construct() 0 6 2
A isClientError() 0 3 2
A statusExists() 0 3 1
A getMessage() 0 3 2
A isSuccess() 0 3 2
1
<?php
2
3
namespace GinoPane\NanoHttpStatus;
4
5
/**
6
 * Class NanoHttpStatus
7
 *
8
 * @author Sergey <Gino Pane> Karavay
9
 */
10
class NanoHttpStatus implements NanoHttpStatusInterface
11
{
12
    /**
13
     * Default placeholder for non-existent status
14
     */
15
    const UNDEFINED_STATUS_MESSAGE = 'Undefined Status';
16
17
    /**
18
     * HTTP status common descriptions
19
     *
20
     * @var array
21
     */
22
    private static $defaultStatuses = [
23
        self::HTTP_CONTINUE => 'Continue',
24
        self::HTTP_SWITCHING_PROTOCOLS => 'Switching Protocols',
25
        self::HTTP_PROCESSING => 'Processing',
26
        self::HTTP_EARLY_HINTS => 'Early Hints',
27
        self::HTTP_OK => 'OK',
28
        self::HTTP_CREATED => 'Created',
29
        self::HTTP_ACCEPTED => 'Accepted',
30
        self::HTTP_NON_AUTHORITATIVE_INFORMATION => 'Non-Authoritative Information',
31
        self::HTTP_NO_CONTENT => 'No Content',
32
        self::HTTP_RESET_CONTENT => 'Reset Content',
33
        self::HTTP_PARTIAL_CONTENT => 'Partial Content',
34
        self::HTTP_MULTI_STATUS => 'Multi-Status',
35
        self::HTTP_ALREADY_REPORTED => 'Already Reported',
36
        self::HTTP_IM_USED => 'IM Used',
37
        self::HTTP_MULTIPLE_CHOICES => 'Multiple Choices',
38
        self::HTTP_MOVED_PERMANENTLY => 'Moved Permanently',
39
        self::HTTP_FOUND => 'Found',
40
        self::HTTP_SEE_OTHER => 'See Other',
41
        self::HTTP_NOT_MODIFIED => 'Not Modified',
42
        self::HTTP_USE_PROXY => 'Use Proxy',
43
        self::HTTP_TEMPORARY_REDIRECT => 'Temporary Redirect',
44
        self::HTTP_PERMANENTLY_REDIRECT => 'Permanent Redirect',
45
        self::HTTP_BAD_REQUEST => 'Bad Request',
46
        self::HTTP_UNAUTHORIZED => 'Unauthorized',
47
        self::HTTP_PAYMENT_REQUIRED => 'Payment Required',
48
        self::HTTP_FORBIDDEN => 'Forbidden',
49
        self::HTTP_NOT_FOUND => 'Not Found',
50
        self::HTTP_METHOD_NOT_ALLOWED => 'Method Not Allowed',
51
        self::HTTP_NOT_ACCEPTABLE => 'Not Acceptable',
52
        self::HTTP_PROXY_AUTHENTICATION_REQUIRED => 'Proxy Authentication Required',
53
        self::HTTP_REQUEST_TIMEOUT => 'Request Timeout',
54
        self::HTTP_CONFLICT => 'Conflict',
55
        self::HTTP_GONE => 'Gone',
56
        self::HTTP_LENGTH_REQUIRED => 'Length Required',
57
        self::HTTP_PRECONDITION_FAILED => 'Precondition Failed',
58
        self::HTTP_PAYLOAD_TOO_LARGE => 'Payload Too Large',
59
        self::HTTP_URI_TOO_LONG => 'URI Too Long',
60
        self::HTTP_UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type',
61
        self::HTTP_RANGE_NOT_SATISFIABLE => 'Requested Range Not Satisfiable',
62
        self::HTTP_EXPECTATION_FAILED => 'Expectation Failed',
63
        self::HTTP_I_AM_A_TEAPOT => 'I\'m a teapot',
64
        self::HTTP_MISDIRECTED_REQUEST => 'Misdirected Request',
65
        self::HTTP_UNPROCESSABLE_ENTITY => 'Unprocessable Entity',
66
        self::HTTP_LOCKED => 'Locked',
67
        self::HTTP_FAILED_DEPENDENCY => 'Failed Dependency',
68
        self::HTTP_UPGRADE_REQUIRED => 'Upgrade Required',
69
        self::HTTP_PRECONDITION_REQUIRED => 'Precondition Required',
70
        self::HTTP_TOO_MANY_REQUESTS => 'Too Many Requests',
71
        self::HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE => 'Request Header Fields Too Large',
72
        self::HTTP_UNAVAILABLE_FOR_LEGAL_REASONS => 'Unavailable For Legal Reasons',
73
        self::HTTP_INTERNAL_SERVER_ERROR => 'Internal Server Error',
74
        self::HTTP_NOT_IMPLEMENTED => 'Not Implemented',
75
        self::HTTP_BAD_GATEWAY => 'Bad Gateway',
76
        self::HTTP_SERVICE_UNAVAILABLE => 'Service Unavailable',
77
        self::HTTP_GATEWAY_TIMEOUT => 'Gateway Timeout',
78
        self::HTTP_VERSION_NOT_SUPPORTED => 'HTTP Version Not Supported',
79
        self::HTTP_VARIANT_ALSO_NEGOTIATES => 'Variant Also Negotiates',
80
        self::HTTP_INSUFFICIENT_STORAGE => 'Insufficient Storage',
81
        self::HTTP_LOOP_DETECTED => 'Loop Detected',
82
        self::HTTP_NOT_EXTENDED => 'Not Extended',
83
        self::HTTP_NETWORK_AUTHENTICATION_REQUIRED => 'Network Authentication Required',
84
    ];
85
86
    /**
87
     * Array of ready-to-use status messages
88
     *
89
     * @var string[]
90
     */
91
    private $statuses = [];
92
93
    public function __construct(array $localize = [])
94
    {
95
        $this->statuses = self::$defaultStatuses;
96
97
        if (!empty($localize)) {
98
            $this->statuses = array_intersect_key($localize, $this->statuses) + $this->statuses;
99
        }
100
    }
101
102
    /**
103
     * Returns 'true' if status code exists, 'false' otherwise
104
     *
105
     * @param int $code
106
     *
107
     * @return bool
108
     */
109
    public function statusExists(int $code): bool
110
    {
111
        return isset($this->statuses[$code]);
112
    }
113
114
    /**
115
     * Returns relevant status message if status exists, 'Undefined Status' is returned otherwise
116
     *
117
     * @param int $code
118
     *
119
     * @return string
120
     */
121
    public function getMessage(int $code): string
122
    {
123
        return $this->statusExists($code) ? $this->statuses[$code] : self::UNDEFINED_STATUS_MESSAGE;
124
    }
125
126
    /**
127
     * Returns 'true' if status exists and belongs to "informational" (1xx) statuses, 'false' otherwise
128
     *
129
     * @param int $code
130
     *
131
     * @return bool
132
     */
133
    public function isInformational(int $code): bool
134
    {
135
        return $this->statusExists($code) && ($this->extractFirstDigit($code) == self::CLASS_INFORMATIONAL);
136
    }
137
138
    /**
139
     * Returns 'true' if status exists and belongs to "success" (2xx) statuses, 'false' otherwise
140
     *
141
     * @param int $code
142
     *
143
     * @return bool
144
     */
145
    public function isSuccess(int $code): bool
146
    {
147
        return $this->statusExists($code) && ($this->extractFirstDigit($code) == self::CLASS_SUCCESS);
148
    }
149
150
    /**
151
     * Returns 'true' if status exists and belongs to "redirection" (3xx) statuses, 'false' otherwise
152
     *
153
     * @param int $code
154
     *
155
     * @return bool
156
     */
157
    public function isRedirection(int $code): bool
158
    {
159
        return $this->statusExists($code) && ($this->extractFirstDigit($code) == self::CLASS_REDIRECTION);
160
    }
161
162
    /**
163
     * Returns 'true' if status exists and belongs to "client error" (4xx) statuses, 'false' otherwise
164
     *
165
     * @param int $code
166
     *
167
     * @return bool
168
     */
169
    public function isClientError(int $code): bool
170
    {
171
        return $this->statusExists($code) && ($this->extractFirstDigit($code) == self::CLASS_CLIENT_ERROR);
172
    }
173
174
    /**
175
     * Returns 'true' if status exists and belongs to "server error" (5xx) statuses, 'false' otherwise
176
     *
177
     * @param int $code
178
     *
179
     * @return bool
180
     */
181
    public function isServerError(int $code): bool
182
    {
183
        return $this->statusExists($code) && ($this->extractFirstDigit($code) == self::CLASS_SERVER_ERROR);
184
    }
185
186
    /**
187
     * Extracts the first digit of the number
188
     *
189
     * @param int $code
190
     *
191
     * @return int
192
     */
193
    private function extractFirstDigit(int $code): int
194
    {
195
        return (int)substr((string)$code, 0, 1);
196
    }
197
}
198