Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
84.62% covered (success)
84.62%
33 / 39
66.67% covered (warning)
66.67%
6 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
Response
84.62% covered (success)
84.62%
33 / 39
66.67% covered (warning)
66.67%
6 / 9
24.93
0.00% covered (danger)
0.00%
0 / 1
 prepareBody
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 getHeadersAsString
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 sendHeaders
71.43% covered (success)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
4.37
 send
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 sendAndExit
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 __toString
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 redirect
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
3
 redirectAndExit
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getMessageFromCode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Http\Server;
15
16use Pop\Http\AbstractResponse;
17use Pop\Http\Parser;
18use Pop\Mime\Part\Body;
19
20/**
21 * HTTP response class
22 *
23 * @category   Pop
24 * @package    Pop\Http
25 * @author     Nick Sagona, III <dev@nolainteractive.com>
26 * @copyright  Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com)
27 * @license    http://www.popphp.org/license     New BSD License
28 * @version    4.1.0
29 */
30class Response extends AbstractResponse
31{
32
33    /**
34     * Prepare response body
35     *
36     * @param  boolean $length
37     * @param  boolean $mb
38     * @return string
39     */
40    public function prepareBody($length = false, $mb = false)
41    {
42        $body = $this->body->render();
43
44        if ($this->hasHeader('Content-Encoding')) {
45            $body = Parser::encodeData($body, strtoupper($this->getHeader('Content-Encoding')->getValue()));
46            if ($length) {
47                $this->addHeader('Content-Length', (($mb) ? mb_strlen($body) : strlen($body)));
48            }
49        } else if ($length) {
50            $this->addHeader('Content-Length', (($mb) ? mb_strlen($body) : strlen($body)));
51        }
52
53        return $body;
54    }
55
56    /**
57     * Get the response headers as a string
58     *
59     * @param  boolean $status
60     * @param  string  $eol
61     * @return string
62     */
63    public function getHeadersAsString($status = null, $eol = "\r\n")
64    {
65        $httpStatus = ($status === true) ? "HTTP/{$this->version} {$this->code} {$this->message}" : $status;
66        return parent::getHeadersAsString($httpStatus, $eol);
67    }
68
69    /**
70     * Send response headers
71     *
72     * @throws Exception
73     * @return void
74     */
75    public function sendHeaders()
76    {
77        if (headers_sent()) {
78            throw new Exception('The headers have already been sent.');
79        }
80
81        header("HTTP/{$this->version} {$this->code} {$this->message}");
82        foreach ($this->headers as $name => $value) {
83            if ($value instanceof \Pop\Mime\Part\Header) {
84                header((string)$value);
85            } else {
86                header($name . ": " . $value);
87            }
88        }
89    }
90
91    /**
92     * Send full response
93     *
94     * @param  int     $code
95     * @param  array   $headers
96     * @param  boolean $length
97     * @return void
98     */
99    public function send($code = null, array $headers = null, $length = false)
100    {
101        if (null !== $code) {
102            $this->setCode($code);
103        }
104        if (null !== $headers) {
105            $this->addHeaders($headers);
106        }
107
108        $body = $this->prepareBody($length);
109
110        $this->sendHeaders();
111        echo $body;
112    }
113
114    /**
115     * Send full response and exit
116     *
117     * @param  int   $code
118     * @param  array $headers
119     * @param  boolean $length
120     * @return void
121     */
122    public function sendAndExit($code = null, array $headers = null, $length = false)
123    {
124        $this->send($code, $headers, $length);
125        exit();
126    }
127
128    /**
129     * Return entire response as a string
130     *
131     * @return string
132     */
133    public function __toString()
134    {
135        $body = $this->prepareBody();
136        return $this->getHeadersAsString(true) . "\r\n" . $body;
137    }
138
139    /**
140     * Send redirect
141     *
142     * @param  string $url
143     * @param  string $code
144     * @param  string $version
145     * @throws Exception
146     * @return void
147     */
148    public static function redirect($url, $code = '302', $version = '1.1')
149    {
150        if (headers_sent()) {
151            throw new Exception('The headers have already been sent.');
152        }
153
154        if (!array_key_exists($code, self::$responseCodes)) {
155            throw new Exception('The header code '. $code . ' is not allowed.');
156        }
157
158        header("HTTP/{$version} {$code} " . self::$responseCodes[$code]);
159        header("Location: {$url}");
160    }
161
162    /**
163     * Send redirect and exit
164     *
165     * @param  string  $url
166     * @param  string  $code
167     * @param  string  $version
168     * @return void
169     */
170    public static function redirectAndExit($url, $code = '302', $version = '1.1')
171    {
172        static::redirect($url, $code, $version);
173        exit();
174    }
175
176    /**
177     * Get response message from code
178     *
179     * @param  int $code
180     * @throws Exception
181     * @return string
182     */
183    public static function getMessageFromCode($code)
184    {
185        if (!array_key_exists($code, self::$responseCodes)) {
186            throw new Exception('The header code ' . $code . ' is not valid.');
187        }
188
189        return self::$responseCodes[$code];
190    }
191
192}