Completed
Push — master ( 475fd8...dd137e )
by Yuichi
07:47 queued 01:16
created

ResponseService::createException()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 13
rs 9.8333
c 0
b 0
f 0
cc 3
nc 3
nop 1
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
    public function __construct(RequestInterface $request, ResponseInterface $response)
32
    {
33
        $this->request = $request;
34
        $this->response = $response;
35
    }
36
37
    /**
38
     * @return bool
39
     */
40
    public function isJsonResponse(): bool
41
    {
42
        $contentType = $this->response->getHeader('Content-Type');
43
        $contentType = is_array($contentType) && isset($contentType[0]) ? $contentType[0] : $contentType;
44
45
        return is_string($contentType) && strpos($contentType, 'application/json') === 0;
46
    }
47
48
49
    /**
50
     * @throws RequestException
51
     */
52
    public function handleDomError(): void
53
    {
54
        $body = (string)$this->response->getBody()->getContents();
55
        $dom = new \DOMDocument('1.0', 'UTF-8');
56
        $dom->preserveWhiteSpace = false;
57
        $dom->formatOutput = true;
58
        if ($dom->loadHTML($body)) {
59
            $title = $dom->getElementsByTagName('title');
60
            if (is_object($title)) {
61
                $title = $title->item(0)->nodeValue;
62
            }
63
            if ($title === 'Error') {
64
                $message = $dom->getElementsByTagName('h3')->item(0)->nodeValue;
65
                throw $this->createException($message);
66
            }
67
            if ($title === 'Unauthorized') {
68
                $message = $dom->getElementsByTagName('h2')->item(0)->nodeValue;
69
                throw $this->createException($message);
70
            }
71
72
            throw $this->createException('Invalid auth.');
73
        }
74
75
        throw new \InvalidArgumentException('Body is not DOM.');
76
    }
77
78
    /**
79
     * @throws RequestException
80
     */
81
    public function handleJsonError(): void
82
    {
83
        try {
84
            $body = (string)$this->response->getBody()->getContents();
85
            $json = \GuzzleHttp\json_decode($body, true);
86
        } catch (\InvalidArgumentException $e) {
87
            return;
88
        } catch (\RuntimeException $e) {
89
            return;
90
        }
91
92
        $message = $json['message'];
93
        if (isset($json['errors']) && is_array($json['errors'])) {
94
            $message .= $this->addErrorMessages($json['errors']);
95
        }
96
97
        throw $this->createException($message);
98
    }
99
100
    /**
101
     * @param array $errors
102
     * @return string
103
     */
104
    private function addErrorMessages(array $errors): string
105
    {
106
        $message = ' (';
107
        foreach ($errors as $k => $err) {
108
            $message .= $k . ' : ';
109
            if (is_array($err['messages'])) {
110
                foreach ($err['messages'] as $m) {
111
                    $message .= $m . ' ';
112
                }
113
            } else {
114
                $message .= $err['messages'];
115
            }
116
        }
117
        $message .= ')';
118
119
        return $message;
120
    }
121
122
    /**
123
     * @param string $message
124
     * @return RequestException
125
     */
126
    public function createException($message): RequestException
127
    {
128
        $level = (int) floor($this->response->getStatusCode() / 100);
129
        $className = RequestException::class;
130
131
        if ($level === 4) {
132
            $className = ClientException::class;
133
        } elseif ($level === 5) {
134
            $className = ServerException::class;
135
        }
136
137
        return new $className($message, $this->request, $this->response);
138
    }
139
}
140