Passed
Push — main ( 22ee9f...77fae7 )
by Peter
02:53
created

ExceptionRenderer::isInDevelopmentEnvironment()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace AbterPhp\Framework\Debug\Exceptions\Handlers\Whoops;
4
5
use Exception;
6
use Opulence\Framework\Debug\Exceptions\Handlers\Http;
7
use Opulence\Http\HttpException;
8
use Throwable;
9
use Whoops\RunInterface;
10
11
/**
12
 * @SuppressWarnings(PHPMD)
13
 */
14
class ExceptionRenderer extends Http\ExceptionRenderer implements Http\IExceptionRenderer
15
{
16
    /** @var RunInterface */
17
    protected $run;
18
19
    /**
20
     * @return bool
21
     */
22
    public function isInDevelopmentEnvironment(): bool
23
    {
24
        return $this->inDevelopmentEnvironment;
25
    }
26
27
    /**
28
     * @param bool $inDevelopmentEnvironment
29
     *
30
     * @return $this
31
     */
32
    public function setInDevelopmentEnvironment(bool $inDevelopmentEnvironment): self
33
    {
34
        $this->inDevelopmentEnvironment = $inDevelopmentEnvironment;
35
36
        return $this;
37
    }
38
39
    /**
40
     * WhoopsRenderer constructor.
41
     *
42
     * @param RunInterface $run
43
     */
44
    public function __construct(RunInterface $run, bool $inDevelopmentEnvironment = false)
45
    {
46
        $this->run = $run;
47
48
        parent::__construct($inDevelopmentEnvironment);
49
    }
50
51
    /**
52
     * @return RunInterface
53
     */
54
    public function getRun()
55
    {
56
        return $this->run;
57
    }
58
59
    /**
60
     * Renders an exception
61
     *
62
     * @param Throwable|Exception $ex The thrown exception
63
     */
64
    public function render($ex)
65
    {
66
        if (!$this->inDevelopmentEnvironment) {
67
            $this->run->writeToOutput(false);
68
69
            $this->run->unregister();
70
71
            $this->devRender($ex);
72
73
            return;
74
        }
75
76
        $this->run->handleException($ex);
77
    }
78
79
    public function devRender($ex)
80
    {
81
        // Add support for HTTP library without having to necessarily depend on it
82
        if ($ex instanceof HttpException) {
83
            $statusCode = $ex->getStatusCode();
84
            $headers    = $ex->getHeaders();
85
        } else {
86
            $statusCode = 500;
87
            $headers    = [];
88
        }
89
90
        // Always get the content, even if headers are sent, so that we can unit test this
91
        $content = $ex->getMessage();
92
93
        if (!headers_sent()) {
94
            header("HTTP/1.1 $statusCode", true, $statusCode);
95
96
            switch ($this->getRequestFormat()) {
97
                case 'json':
98
                    $headers['Content-Type'] = 'application/json';
99
                    break;
100
                default:
101
                    $content                 = sprintf(
102
                        '<!DOCTYPE html>
103
<html>
104
    <head>
105
        <meta name="viewport" content="initial-scale=1"/>
106
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
107
            integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
108
            crossorigin="anonymous">
109
    </head>
110
    <body>
111
        <main class="main">
112
            <div class="container">
113
                <div class="row">
114
                    <div class="col-sm">
115
                        <div class="alert alert-danger" role="alert">
116
                            <h4 class="alert-heading">Exception: %s</h4>
117
                            <p>%s</p>
118
                            <hr>
119
                            <p class="mb-0">
120
                                <a href="#" class="btn btn-danger btn-lg active" role="button" aria-pressed="true"
121
                                onclick="location.reload(); return false;">Try again</a>
122
                                <a href="#" class="btn btn-primary btn-lg active" role="button" aria-pressed="true"
123
                                onclick="window.history.back(); return false;">Back to previous page</a>
124
                            </p>
125
                        </div>
126
                    </div>
127
                </div>
128
            </div>
129
        </main>
130
    </body>
131
</html>',
132
                        get_class($ex),
133
                        $ex->getMessage()
134
                    );
135
                    $headers['Content-Type'] = 'text/html';
136
            }
137
138
            foreach ($headers as $name => $values) {
139
                $values = (array)$values;
140
141
                foreach ($values as $value) {
142
                    header("$name:$value", false, $statusCode);
143
                }
144
            }
145
146
            echo $content;
147
            // To prevent any potential output buffering, let's flush
148
            flush();
149
        }
150
    }
151
}
152