Passed
Push — master ( 1bc9e0...617de7 )
by Ryosuke
03:07
created

ResponseBodyDecoder::normalize()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7

Importance

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