Passed
Branch master (0d8fc3)
by Tomáš
12:26
created

BadRequestException::setErrorsForPackage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 3
nop 2
dl 0
loc 13
ccs 6
cts 6
cp 1
crap 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Inspirum\Balikobot\Exception;
6
7
use Inspirum\Balikobot\Definitions\Response;
8
use Throwable;
9
use function is_array;
10
use function is_numeric;
11
12
final class BadRequestException extends BaseException
13
{
14
    /**
15
     * BadRequestException constructor
16
     *
17
     * @param array<mixed>    $response
18
     * @param int             $statusCode
19
     * @param \Throwable|null $previous
20
     * @param string|null     $message
21
     */
22 373
    public function __construct(
23
        array $response,
24
        int $statusCode = 400,
25
        ?Throwable $previous = null,
26
        ?string $message = null
27
    ) {
28 373
        $this->setErrors($response);
29
30 373
        parent::__construct($response, $statusCode, $previous, $message);
31
    }
32
33
    /**
34
     * Set errors from response
35
     *
36
     * @param array<mixed> $response
37
     *
38
     * @return void
39
     */
40 373
    private function setErrors(array $response): void
41
    {
42 373
        $i = 0;
43
44 373
        $packages = $this->resolveErrorsData($response);
45
46
        // add errors from all packages
47 373
        while (isset($packages[$i])) {
48 31
            if (is_array($packages[$i])) {
49 31
                $this->setErrorsForPackage($i, $packages[$i]);
50 2
            } elseif (is_numeric($packages[$i]) && $packages[$i] >= 400) {
51 1
                $this->setError($i, 'status', $this->getErrorMessage('status', (int) $packages[$i]));
52
            } else {
53 1
                $this->setError($i, 'status', 'Nespecifikovaná chyba.');
54
            }
55
56
            // try next package
57 31
            $i++;
58
        }
59
    }
60
61
    /**
62
     * Resolve errors data array
63
     *
64
     * @param array<mixed> $response
65
     *
66
     * @return array<mixed>
67
     */
68 373
    private function resolveErrorsData(array $response): array
69
    {
70 373
        if (isset($response['packages'])) {
71 15
            return $response['packages'];
72
        }
73
74 358
        if (isset($response['errors'])) {
75 2
            return $response['errors'];
76
        }
77
78 356
        return $response;
79
    }
80
81
    /**
82
     * Set errors for package
83
     *
84
     * @param int          $number
85
     * @param array<mixed> $response
86
     *
87
     * @return void
88
     */
89 31
    private function setErrorsForPackage(int $number, array $response): void
90
    {
91
        // response does not have full errors
92 31
        if (isset($response['errors']) === false) {
93
            // try to resolve errors from codes
94 23
            $this->setErrorsFromResponseCodes($number, $response);
95
96 23
            return;
97
        }
98
99
        // set errors for given package
100 8
        foreach ($response['errors'] as $error) {
101 8
            $this->setError($number, $error['attribute'], $error['message']);
102
        }
103
    }
104
105
    /**
106
     * Set errors from codes
107
     *
108
     * @param int                      $number
109
     * @param array<string,int|string> $response
110
     *
111
     * @return void
112
     */
113 23
    private function setErrorsFromResponseCodes(int $number, array $response): void
114
    {
115 23
        foreach ($response as $key => $code) {
116
            // skip non-numeric codes
117 23
            if (is_numeric($code) === false || $code < 400) {
118 19
                continue;
119
            }
120
121
            // set errors from given package from response codes
122 15
            $this->setError($number, $key, $this->getErrorMessage($key, (int) $code));
123
        }
124
    }
125
126
    /**
127
     * Get error message from variables
128
     *
129
     * @param string $key
130
     * @param int    $code
131
     *
132
     * @return string
133
     */
134 15
    private function getErrorMessage(string $key, int $code): string
135
    {
136
        // get error message from code
137 15
        if ($key === 'status') {
138 11
            return Response::STATUS_CODE_ERRORS[$code] ?? Response::STATUS_CODE_ERRORS[500];
139
        }
140
141 12
        if (isset(Response::PACKAGE_DATA_KEY_ERRORS[$code][$key])) {
142 5
            return Response::PACKAGE_DATA_KEY_ERRORS[$code][$key];
143
        }
144
145 10
        return Response::PACKAGE_DATA_ERRORS[$code] ?? 'Nespecifikovaná chyba.';
146
    }
147
148
    /**
149
     * Set new error message
150
     *
151
     * @param int    $number
152
     * @param string $key
153
     * @param string $error
154
     *
155
     * @return void
156
     */
157 23
    private function setError(int $number, string $key, string $error): void
158
    {
159 23
        $this->errors[$number][$key] = $error;
160
    }
161
}
162