Completed
Push — master ( 360314...c2aa1e )
by Ryosuke
08:47
created

ResponseBodyDecoder::handleJsonAndXml()   D

Complexity

Conditions 9
Paths 14

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 20.5013

Importance

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