Passed
Pull Request — master (#77)
by Yuichi
11:08
created

ResponseService::handleJsonError()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
c 1
b 0
f 0
nc 6
nop 0
dl 0
loc 17
ccs 11
cts 11
cp 1
crap 5
rs 9.6111
1
<?php
2
3
namespace CybozuHttp\Service;
4
5
use GuzzleHttp\Exception\ClientException;
6
use GuzzleHttp\Exception\RequestException;
7
use GuzzleHttp\Exception\ServerException;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\Http\Message\ResponseInterface;
10
11
/**
12
 * @author ochi51 <[email protected]>
13
 */
14
class ResponseService
15
{
16
    /**
17
     * @var RequestInterface
18
     */
19
    private $request;
20
21
    /**
22
     * @var ResponseInterface
23
     */
24
    private $response;
25
26
    /**
27
     * ResponseService constructor.
28
     * @param RequestInterface $request
29
     * @param ResponseInterface $response
30
     */
31 65
    public function __construct(RequestInterface $request, ResponseInterface $response)
32
    {
33 65
        $this->request = $request;
34 65
        $this->response = $response;
35
    }
36
37
    /**
38
     * @return bool
39
     */
40 62
    public function isJsonResponse(): bool
41
    {
42 62
        $contentType = $this->response->getHeader('Content-Type');
43 62
        $contentType = is_array($contentType) && isset($contentType[0]) ? $contentType[0] : $contentType;
44
45 62
        return is_string($contentType) && strpos($contentType, 'application/json') === 0;
46
    }
47
48
    /**
49
     * @return bool
50
     */
51 1
    public function isHtmlResponse(): bool
52
    {
53 1
        $contentType = $this->response->getHeader('Content-Type');
54 1
        $contentType = is_array($contentType) && isset($contentType[0]) ? $contentType[0] : $contentType;
55
56 1
        return is_string($contentType) && strpos($contentType, 'text/html') === 0;
57
    }
58
59
60
    /**
61
     * @throws RequestException
62
     */
63 1
    public function handleDomError(): void
64
    {
65 1
        $body = (string)$this->response->getBody()->getContents();
66 1
        $dom = new \DOMDocument('1.0', 'UTF-8');
67 1
        $dom->preserveWhiteSpace = false;
68 1
        $dom->formatOutput = true;
69 1
        if ($dom->loadHTML($body)) {
70 1
            $title = $dom->getElementsByTagName('title');
71 1
            if (is_object($title)) {
72 1
                $title = $title->item(0)->nodeValue;
73
            }
74 1
            if ($title === 'Error') {
75 1
                $message = $dom->getElementsByTagName('h3')->item(0)->nodeValue;
76 1
                throw $this->createException($message);
77
            }
78 1
            if ($title === 'Unauthorized') {
79 1
                $message = $dom->getElementsByTagName('h2')->item(0)->nodeValue;
80 1
                throw $this->createException($message);
81
            }
82
83 1
            throw $this->createException('Invalid auth.');
84
        }
85
86
        throw new \InvalidArgumentException('Body is not DOM.');
87
    }
88
89
    /**
90
     * @throws RequestException
91
     */
92 4
    public function handleJsonError(): void
93
    {
94
        try {
95 4
            $body = (string)$this->response->getBody()->getContents();
96 4
            $json = \GuzzleHttp\json_decode($body, true);
0 ignored issues
show
Deprecated Code introduced by
The function GuzzleHttp\json_decode() has been deprecated: json_decode will be removed in guzzlehttp/guzzle:8.0. Use Utils::jsonDecode instead. ( Ignorable by Annotation )

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

96
            $json = /** @scrutinizer ignore-deprecated */ \GuzzleHttp\json_decode($body, true);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
97 1
        } catch (\InvalidArgumentException $e) {
98 1
            return;
99 1
        } catch (\RuntimeException $e) {
100 1
            return;
101
        }
102
103 4
        $message = $json['message'];
104 4
        if (isset($json['errors']) && is_array($json['errors'])) {
105 1
            $message .= $this->addErrorMessages($json['errors']);
106
        }
107
108 4
        throw $this->createException($message);
109
    }
110
111
    /**
112
     * @param array $errors
113
     * @return string
114
     */
115 1
    private function addErrorMessages(array $errors): string
116
    {
117 1
        $message = ' (';
118 1
        foreach ($errors as $k => $err) {
119 1
            $message .= $k . ' : ';
120 1
            if (is_array($err['messages'])) {
121 1
                foreach ($err['messages'] as $m) {
122 1
                    $message .= $m . ' ';
123
                }
124
            } else {
125 1
                $message .= $err['messages'];
126
            }
127
        }
128 1
        $message .= ')';
129
130 1
        return $message;
131
    }
132
133
    /**
134
     * @param string $message
135
     * @return RequestException
136
     */
137 5
    public function createException($message): RequestException
138
    {
139 5
        $level = (int) floor($this->response->getStatusCode() / 100);
140 5
        $className = RequestException::class;
141
142 5
        if ($level === 4) {
143 3
            $className = ClientException::class;
144 3
        } elseif ($level === 5) {
145 3
            $className = ServerException::class;
146
        }
147
148 5
        return new $className($message, $this->request, $this->response);
149
    }
150
}
151