44
55namespace ApiSkeletons \Laravel \ApiProblem ;
66
7- use Exception ;
87use ApiSkeletons \Laravel \ApiProblem \Exception \InvalidArgumentException ;
98use ApiSkeletons \Laravel \ApiProblem \Exception \ProblemExceptionInterface ;
9+ use Exception ;
1010use Throwable ;
1111
1212use function array_key_exists ;
1313use function array_keys ;
1414use function array_merge ;
15+ use function assert ;
1516use function count ;
1617use function get_class ;
1718use function in_array ;
@@ -33,45 +34,37 @@ class ApiProblem
3334 /**
3435 * Additional details to include in report.
3536 *
36- * @var array
37+ * @var string[]
3738 */
38- protected $ additionalDetails = [];
39+ protected array $ additionalDetails = [];
3940
4041 /**
4142 * URL describing the problem type; defaults to HTTP status codes.
42- *
43- * @var string
4443 */
45- protected $ type = 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html ' ;
44+ protected string $ type = 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html ' ;
4645
4746 /**
4847 * Description of the specific problem.
49- *
50- * @var string|Exception|Throwable
5148 */
52- protected $ detail = '' ;
49+ protected string | Throwable | Throwable $ detail = '' ;
5350
5451 /**
5552 * Whether or not to include a stack trace and previous
5653 * exceptions when an exception is provided for the detail.
57- *
58- * @var bool
5954 */
60- protected $ detailIncludesStackTrace = false ;
55+ protected bool $ detailIncludesStackTrace = false ;
6156
6257 /**
6358 * HTTP status for the error.
64- *
65- * @var int
6659 */
67- protected $ status ;
60+ protected int $ status ;
6861
6962 /**
7063 * Normalized property names for overloading.
7164 *
72- * @var array
65+ * @var string[]
7366 */
74- protected $ normalizedProperties = [
67+ protected array $ normalizedProperties = [
7568 'type ' => 'type ' ,
7669 'status ' => 'status ' ,
7770 'title ' => 'title ' ,
@@ -81,9 +74,9 @@ class ApiProblem
8174 /**
8275 * Status titles for common problems.
8376 *
84- * @var array
77+ * @var string[]
8578 */
86- protected $ problemStatusTitles = [
79+ protected array $ problemStatusTitles = [
8780 // CLIENT ERROR
8881 400 => 'Bad Request ' ,
8982 401 => 'Unauthorized ' ,
@@ -127,32 +120,28 @@ class ApiProblem
127120
128121 /**
129122 * Title of the error.
130- *
131- * @var string
132123 */
133- protected $ title ;
124+ protected string $ title ;
134125
135126 /**
136127 * Create an instance using the provided information. If nothing is
137128 * provided for the type field, the class default will be used;
138129 * if the status matches any known, the title field will be selected
139130 * from $problemStatusTitles as a result.
140131 *
141- * @param int|string $status
142- * @param string|Exception|Throwable $detail
143- * @param string $type
144- * @param string $title
145- * @param array $additional
132+ * @param string[] $additional
146133 */
147- public function __construct ($ status , $ detail , $ type = null , $ title = null , array $ additional = [])
134+ public function __construct (int | string $ status , string | Throwable | Throwable $ detail , ? string $ type = null , ? string $ title = null , array $ additional = [])
148135 {
149136 if ($ detail instanceof ProblemExceptionInterface) {
150- if (null === $ type ) {
137+ if ($ type === null ) {
151138 $ type = $ detail ->getType ();
152139 }
153- if (null === $ title ) {
140+
141+ if ($ title === null ) {
154142 $ title = $ detail ->getTitle ();
155143 }
144+
156145 if (empty ($ additional )) {
157146 $ additional = $ detail ->getAdditionalDetails ();
158147 }
@@ -171,7 +160,7 @@ public function __construct($status, $detail, $type = null, $title = null, array
171160 $ this ->detail = $ detail ;
172161 $ this ->title = $ title ;
173162
174- if (null !== $ type ) {
163+ if ($ type !== null ) {
175164 $ this ->type = $ type ;
176165 }
177166
@@ -181,11 +170,9 @@ public function __construct($status, $detail, $type = null, $title = null, array
181170 /**
182171 * Retrieve properties.
183172 *
184- * @param string $name
185- * @return mixed
186173 * @throws InvalidArgumentException
187174 */
188- public function __get ($ name )
175+ public function __get (string $ name ): mixed
189176 {
190177 $ normalized = strtolower ($ name );
191178 if (in_array ($ normalized , array_keys ($ this ->normalizedProperties ))) {
@@ -211,28 +198,26 @@ public function __get($name)
211198 /**
212199 * Cast to an array.
213200 *
214- * @return array
201+ * @return string[]
215202 */
216- public function toArray ()
203+ public function toArray (): array
217204 {
218205 $ problem = [
219206 'type ' => $ this ->type ,
220207 'title ' => $ this ->getTitle (),
221208 'status ' => $ this ->getStatus (),
222209 'detail ' => $ this ->getDetail (),
223210 ];
211+
224212 // Required fields should always overwrite additional fields
225213 return array_merge ($ this ->additionalDetails , $ problem );
226214 }
227215
228216 /**
229217 * Set the flag indicating whether an exception detail should include a
230218 * stack trace and previous exception information.
231- *
232- * @param bool $flag
233- * @return ApiProblem
234219 */
235- public function setDetailIncludesStackTrace ($ flag )
220+ public function setDetailIncludesStackTrace (bool $ flag ): ApiProblem
236221 {
237222 $ this ->detailIncludesStackTrace = (bool ) $ flag ;
238223
@@ -244,10 +229,8 @@ public function setDetailIncludesStackTrace($flag)
244229 *
245230 * If an exception was provided, creates the detail message from it;
246231 * otherwise, detail as provided is used.
247- *
248- * @return string
249232 */
250- protected function getDetail ()
233+ protected function getDetail (): string
251234 {
252235 if ($ this ->detail instanceof Throwable || $ this ->detail instanceof Exception) {
253236 return $ this ->createDetailFromException ();
@@ -281,17 +264,15 @@ protected function getStatus(): int
281264 * string 'Unknown'.
282265 *
283266 * Otherwise, use the title provided.
284- *
285- * @return string
286267 */
287- protected function getTitle ()
268+ protected function getTitle (): string
288269 {
289- if (null !== $ this ->title ) {
270+ if ($ this ->title !== null ) {
290271 return $ this ->title ;
291272 }
292273
293274 if (
294- null === $ this ->title
275+ $ this ->title === null
295276 && $ this ->type === 'http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html '
296277 && array_key_exists ($ this ->getStatus (), $ this ->problemStatusTitles )
297278 ) {
@@ -302,7 +283,7 @@ protected function getTitle()
302283 return get_class ($ this ->detail );
303284 }
304285
305- if (null === $ this ->title ) {
286+ if ($ this ->title === null ) {
306287 return 'Unknown ' ;
307288 }
308289
@@ -311,13 +292,11 @@ protected function getTitle()
311292
312293 /**
313294 * Create detail message from an exception.
314- *
315- * @return string
316295 */
317- protected function createDetailFromException ()
296+ protected function createDetailFromException (): string
318297 {
319- /** @var Exception|Throwable $e */
320298 $ e = $ this ->detail ;
299+ assert ($ e instanceof Exception || $ e instanceof Throwable);
321300
322301 if (! $ this ->detailIncludesStackTrace ) {
323302 return $ e ->getMessage ();
@@ -336,6 +315,7 @@ protected function createDetailFromException()
336315 ];
337316 $ e = $ e ->getPrevious ();
338317 }
318+
339319 if (count ($ previous )) {
340320 $ this ->additionalDetails ['exception_stack ' ] = $ previous ;
341321 }
@@ -345,13 +325,11 @@ protected function createDetailFromException()
345325
346326 /**
347327 * Create HTTP status from an exception.
348- *
349- * @return int|string
350328 */
351- protected function createStatusFromException ()
329+ protected function createStatusFromException (): int | string
352330 {
353- /** @var Exception|Throwable $e */
354- $ e = $ this -> detail ;
331+ $ e = $ this -> detail ;
332+ assert ( $ e instanceof Exception || $ e instanceof Throwable) ;
355333 $ status = $ e ->getCode ();
356334
357335 if ($ status ) {
0 commit comments