Completed
Push — master ( 3cf178...59e65f )
by Ryosuke
03:33
created

ResponseBodyDecoder::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 3
crap 2
1
<?php
2
3
namespace mpyw\Cowitter\Helpers;
4
5
use mpyw\Cowitter\HttpException;
6
use mpyw\Cowitter\Response;
7
use mpyw\Cowitter\Media;
8
9
class ResponseBodyDecoder
10
{
11
    protected $response;
12
    protected $ch;
13
    protected $info;
14
    protected $bodyBuffer;
15
16 24
    public static function getDecodedResponse(Response $response, $ch, $body_buffer = null)
17 24
    {
18 24
        $static = new static($response, $ch, $body_buffer);
19 24
        return $response->withDecodedContent($static->normalizeImpl());
20
    }
21
22 24
    protected function __construct(Response $response, $ch, $body_buffer = null)
23 24
    {
24 24
        $this->response = $response;
25 24
        $this->ch = $ch;
26 24
        $this->info = curl_getinfo($ch);
27 24
        $this->bodyBuffer = $body_buffer === null ? $response->getRawContent() : $body_buffer;
28 24
    }
29
30 24
    protected function normalizeImpl()
31 24
    {
32 24
        if ($this->bodyBuffer === '') {
33 1
            return $this->handleEmptyBody();
34
        }
35 23
        if (preg_match('@\A(?:image|video)/@', $this->info['content_type'])) {
36 1
            return new Media($this->info['content_type'], $this->bodyBuffer);
37
        }
38 22
        if (null !== $obj = $this->handleJsonAndXml()) {
39 15
            return $obj;
40
        }
41 3
        if (strip_tags($this->bodyBuffer) === $this->bodyBuffer) {
42 1
            return $this->handleText();
43
        }
44 2
        if ($this->info['http_code'] >= 400 && preg_match("@<(?:pre|h1)>([^<]++)</(?:pre|h1)>@", $this->bodyBuffer, $matches)) {
45 1
            throw new HttpException(trim($matches[1]), -1, $this->ch, $this->response);
46
        }
47 1
        throw new \UnexpectedValueException('Malformed response detected: ' . $this->bodyBuffer);
48
    }
49
50 1
    protected function handleEmptyBody()
51 1
    {
52 1
        if ($this->info['http_code'] >= 200 && $this->info['http_code'] <= 204) {
53
            $message = 'Your request has been successfully sent. (This is a message generated by Cowitter)';
54
            return (object)['message' => $message];
55
        }
56 1
        throw new HttpException(
57 1
            "The server returned the status {$this->info['http_code']} with empty response. (This is a message generated by Cowitter)",
58 1
            -1,
59 1
            $this->ch,
60 1
            $this->response
61
        );
62
    }
63
64 22
    protected function handleJsonAndXml()
65 22
    {
66 22
        $orig = libxml_use_internal_errors(true);
67
        try {
68
            if (
69 22
                null  === $obj = json_decode(preg_replace('@\A/\*{2}/[^(]++\((.+)\);\z@s', '$1', $this->bodyBuffer)) and
70 22
                false === $obj = json_decode(json_encode(simplexml_load_string($this->bodyBuffer)))
71
            ) {
72 3
                return;
73
            }
74 19
        } finally {
75 22
            libxml_clear_errors();
76 22
            libxml_use_internal_errors($orig);
77
        }
78 19
        if (!empty($obj->error)) {
79 2
            $errors = $obj->error;
80 17
        } elseif (!empty($obj->errors)) {
81 2
            $errors = $obj->errors;
82
        } else {
83 15
            return $obj;
84
        }
85 4
        if (!is_array($errors)) {
86 3
            $errors = [$errors];
87
        }
88 4
        $messages = [];
89 4
        $code = -1;
90 4
        foreach ($errors as $error) {
91 4
            if (isset($error->code)) {
92 1
                $code = (int)filter_var($error->code);
93
            }
94 4
            $messages[] = (string)filter_var(isset($error->message) ? $error->message : $error);
95
        }
96 4
        throw new HttpException(implode("\n", $messages), $code, $this->ch, $this->response);
97
    }
98
99 1
    protected function handleText()
100 1
    {
101 1
        parse_str($this->bodyBuffer, $obj);
102 1
        $obj = (object)$obj;
103 1
        if (isset($obj->oauth_token, $obj->oauth_token_secret)) {
104
            return $obj;
105
        }
106 1
        throw new HttpException(trim($this->bodyBuffer), -1, $this->ch, $this->response);
107
    }
108
}
109