Exception::prepare()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php declare(strict_types=1);
2
3
namespace Meek\Http;
4
5
use Exception as PhpException;
6
use InvalidArgumentException;
7
use Psr\Http\Message\ResponseInterface;
8
9
/**
10
 * Exception base class for handling HTTP errors.
11
 *
12
 * @author Nathan Bishop <[email protected]> (https://nathanbishop.name)
13
 * @copyright 2016 Nathan Bishop
14
 * @license The MIT license.
15
 */
16
abstract class Exception extends PhpException
17
{
18
    /**
19
     * @var integer The status code.
20
     */
21
    private $statusCode;
22
23
    /**
24
     * @var string The reason phrase.
25
     */
26
    private $reasonPhrase;
27
28
    /**
29
     * @var string[][] The headers.
30
     */
31
    private $headers;
32
33
    /**
34
     * Creates a new HTTP client error exception.
35
     *
36
     * @param integer $statusCode A client error status code.
37
     * @param string $reasonPhrase A reason phrase for the status code.
38
     * @param string[][] $headers Headers to be sent along when preparing the exception's response.
39
     * @throws InvalidArgumentException If a client error status code was not provided.
40
     * @throws InvalidArgumentException If the reason phrase is empty.
41
     */
42 7
    public function __construct(int $statusCode, string $reasonPhrase, array $headers = [])
43
    {
44 7
        $this->assertStatusCodeIsInRange($statusCode);
45
46 7
        if (empty($reasonPhrase)) {
47 1
            throw new InvalidArgumentException('The reason phrase cannot be empty');
48
        }
49
50 6
        $this->statusCode = $statusCode;
51 6
        $this->reasonPhrase = $reasonPhrase;
52 6
        $this->headers = $headers;
53
54 6
        parent::__construct($this->reasonPhrase, $this->statusCode);
55 6
    }
56
57
    /**
58
     * Retrieve the status code.
59
     *
60
     * @return integer The status code.
61
     */
62 1
    public function getStatusCode(): int
63
    {
64 1
        return $this->statusCode;
65
    }
66
67
    /**
68
     * Retrieve the reason phrase.
69
     *
70
     * @return string The reason phrase.
71
     */
72 1
    public function getReasonPhrase(): string
73
    {
74 1
        return $this->reasonPhrase;
75
    }
76
77
    /**
78
     * Retrieve the headers that should be sent along with the HTTP exception response.
79
     *
80
     * @return string[][] Headers to be sent, in a PSR7 compatible format.
81
     */
82 1
    public function getHeaders(): array
83
    {
84 1
        return $this->headers;
85
    }
86
87
    /**
88
     * Prepares a response to send, from the HTTP exception, with things like status code, reason phrase and headers.
89
     *
90
     * @param ResponseInterface $response The response to prepare.
91
     * @return ResponseInterface The prepared response.
92
     */
93 3
    public function prepare(ResponseInterface $response): ResponseInterface
94
    {
95 3
        $response = $response->withStatus($this->getStatusCode(), $this->getReasonPhrase());
96
97 3
        foreach ($this->getHeaders() as $name => $value) {
98 1
            $response = $response->withAddedHeader($name, $value);
99
        }
100
101 3
        return $response;
102
    }
103
104
    /**
105
     * Magic method to allow the exception to be cast to a string.
106
     *
107
     * @return string The status code and reason phrase on one line.
108
     */
109 1
    public function __toString(): string
110
    {
111 1
        return sprintf('%d %s', $this->getStatusCode(), $this->getReasonPhrase());
112
    }
113
114
    /**
115
     * Validate status code is in range of sub class.
116
     *
117
     * @param integer $statusCode The status code to check against.
118
     * @throws InvalidArgumentException If the status code is too low or too high.
119
     */
120
    abstract protected function assertStatusCodeIsInRange(int $statusCode): void;
121
}
122