Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
89.29% covered (success)
89.29%
25 / 28
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Response
89.29% covered (success)
89.29%
25 / 28
66.67% covered (warning)
66.67%
2 / 3
16.31
0.00% covered (danger)
0.00%
0 / 1
 getParsedResponse
83.33% covered (success)
83.33%
15 / 18
0.00% covered (danger)
0.00%
0 / 1
9.37
 collect
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 json
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Http\Client;
16
17use Pop\Http\AbstractResponse;
18use Pop\Http\Parser;
19use Pop\Utils\Collection;
20
21/**
22 * HTTP client response class
23 *
24 * @category   Pop
25 * @package    Pop\Http
26 * @author     Nick Sagona, III <nick@popphp.org>
27 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
28 * @license    https://www.popphp.org/license     New BSD License
29 * @version    6.0.0
30 */
31class Response extends AbstractResponse
32{
33
34    /**
35     * Get the parsed response
36     *
37     * @return mixed
38     */
39    public function getParsedResponse(): mixed
40    {
41        $parsedResponse         = null;
42        $contentType            = null;
43        $contentEncoding        = null;
44        $contentTypeHeaders     = ['Content-Type', 'Content-type', 'content-type'];
45        $contentEncodingHeaders = ['Content-Encoding', 'Content-encoding', 'content-encoding'];
46
47        if ($this->hasBody()) {
48            $rawResponse = $this->getBody()->getContent();
49            foreach ($contentEncodingHeaders as $contentEncodingHeader) {
50                if ($this->hasHeader($contentEncodingHeader) && (count($this->getHeaderObject($contentEncodingHeader)->getValues()) == 1)) {
51                    $contentEncoding = (string)$this->getHeaderObject($contentEncodingHeader)->getValue(0);
52                    break;
53                }
54            }
55
56            foreach ($contentTypeHeaders as $contentTypeHeader) {
57                if ($this->hasHeader($contentTypeHeader) && (count($this->getHeaderObject($contentTypeHeader)->getValues()) == 1)) {
58                    $contentType    = (string)$this->getHeaderObject($contentTypeHeader)->getValue(0);
59                    $parsedResponse = Parser::parseDataByContentType($rawResponse, $contentType, $contentEncoding);
60                    if ($parsedResponse != $rawResponse) {
61                        break;
62                    }
63                }
64            }
65        }
66
67        return $parsedResponse;
68    }
69
70    /**
71     * Attempt to create a collection object from the response.
72     * Attempts a JSON decode on any content string that returns unparsed.
73     *
74     * @param  bool $forceJson
75     * @return Collection
76     */
77    public function collect(bool $forceJson = true): Collection
78    {
79        $data = ($forceJson) ? $this->json() : $this->getParsedResponse();
80
81        // Fall back to empty array on fail
82        if (!is_array($data)) {
83            $data = [];
84        }
85
86        return new Collection($data);
87    }
88
89    /**
90     * Attempts to JSON-decode any content string that returns unparsed.
91     *
92     * @return array
93     */
94    public function json(): array
95    {
96        $content = $this->getParsedResponse();
97
98        if (is_string($content)) {
99            $json = @json_decode($content, true);
100            if (json_last_error() === JSON_ERROR_NONE) {
101                $content = $json;
102            }
103        }
104
105        return (is_array($content)) ? $content : [];
106    }
107
108}