Whoops::process()   B
last analyzed

Complexity

Conditions 7
Paths 180

Size

Total Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 50
rs 7.6242
c 0
b 0
f 0
cc 7
nc 180
nop 2
1
<?php
2
declare(strict_types = 1);
3
4
namespace Middlewares;
5
6
use Middlewares\Utils\Traits\HasResponseFactory;
7
use Middlewares\Utils\Factory;
8
use Psr\Http\Message\ResponseFactoryInterface;
9
use Psr\Container\ContainerInterface;
10
use Psr\Http\Message\ResponseInterface;
11
use Psr\Http\Message\ServerRequestInterface;
12
use Psr\Http\Server\MiddlewareInterface;
13
use Psr\Http\Server\RequestHandlerInterface;
14
use Whoops\Handler\JsonResponseHandler;
15
use Whoops\Handler\PlainTextHandler;
16
use Whoops\Handler\PrettyPageHandler;
17
use Whoops\Handler\XmlResponseHandler;
18
use Whoops\Run;
19
use Whoops\Util\SystemFacade;
20
21
class Whoops implements MiddlewareInterface
22
{
23
    use HasResponseFactory;
24
25
    /**
26
     * @var Run|null
27
     */
28
    private $whoops;
29
30
    /**
31
     * @var SystemFacade|null
32
     */
33
    private $system;
34
35
    /**
36
     * @var bool Whether catch errors or not
37
     */
38
    private $catchErrors = true;
39
40
    /**
41
     * @var ContainerInterface|null
42
     */
43
    private $handlerContainer;
44
45
    /**
46
     * Set the whoops instance.
47
     */
48
    public function __construct(
49
        Run $whoops = null,
50
        SystemFacade $system = null,
51
        ResponseFactoryInterface $responseFactory = null
52
    ) {
53
        $this->whoops = $whoops;
54
        $this->system = $system;
55
        $this->responseFactory = $responseFactory ?: Factory::getResponseFactory();
56
    }
57
58
    /**
59
     * Whether catch errors or not.
60
     */
61
    public function catchErrors(bool $catchErrors = true): self
62
    {
63
        $this->catchErrors = $catchErrors;
64
65
        return $this;
66
    }
67
68
    /**
69
     * Set the PSR-11 container to create the error handler using the Accept header
70
     */
71
    public function handlerContainer(ContainerInterface $handlerContainer): self
72
    {
73
        $this->handlerContainer = $handlerContainer;
74
75
        return $this;
76
    }
77
78
    /**
79
     * Process a server request and return a response.
80
     */
81
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
82
    {
83
        ob_start();
84
        $level = ob_get_level();
85
86
        $method = Run::EXCEPTION_HANDLER;
87
        $whoops = $this->whoops ?: $this->getWhoopsInstance($request);
88
89
        $whoops->allowQuit(false);
90
        $whoops->writeToOutput(false);
91
        $whoops->sendHttpCode(false);
92
93
        //Catch errors means register whoops globally
94
        if ($this->catchErrors) {
95
            $whoops->register();
96
97
            $shutdown = function () use ($whoops) {
98
                $whoops->allowQuit(true);
99
                $whoops->writeToOutput(true);
100
                $whoops->sendHttpCode(true);
101
102
                $method = Run::SHUTDOWN_HANDLER;
103
                $whoops->$method();
104
            };
105
106
            if ($this->system) {
107
                $this->system->registerShutdownFunction($shutdown);
108
            } else {
109
                register_shutdown_function($shutdown);
110
            }
111
        }
112
113
        try {
114
            $response = $handler->handle($request);
115
        } catch (\Throwable $exception) {
116
            $response = $this->createResponse(500);
117
            $response->getBody()->write($whoops->$method($exception));
118
            $response = self::updateResponseContentType($response, $whoops);
119
        } finally {
120
            while (ob_get_level() >= $level) {
121
                ob_end_clean();
122
            }
123
        }
124
125
        if ($this->catchErrors) {
126
            $whoops->unregister();
127
        }
128
129
        return $response;
130
    }
131
132
    /**
133
     * Returns the whoops instance or create one.
134
     */
135
    private function getWhoopsInstance(ServerRequestInterface $request): Run
136
    {
137
        if (!$this->system) {
138
            $this->system = new SystemFacade();
139
        }
140
141
        $whoops = new Run($this->system);
142
        $container = $this->handlerContainer ?: new WhoopsHandlerContainer();
143
        $handler = $container->get($request->getHeaderLine('Accept'));
144
        $whoops->pushHandler($handler);
145
146
        return $whoops;
147
    }
148
149
    /**
150
     * Returns the content-type for the whoops instance
151
     */
152
    private static function updateResponseContentType(ResponseInterface $response, Run $whoops): ResponseInterface
153
    {
154
        if (1 !== count($whoops->getHandlers())) {
155
            return $response;
156
        }
157
158
        $handler = current($whoops->getHandlers());
159
160
        if ($handler instanceof PrettyPageHandler) {
0 ignored issues
show
Bug introduced by Antonio J. García Lagar
The class Whoops\Handler\PrettyPageHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
161
            return $response->withHeader('Content-Type', 'text/html');
162
        }
163
164
        if ($handler instanceof JsonResponseHandler) {
0 ignored issues
show
Bug introduced by Antonio J. García Lagar
The class Whoops\Handler\JsonResponseHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
165
            return $response->withHeader('Content-Type', 'application/json');
166
        }
167
168
        if ($handler instanceof XmlResponseHandler) {
0 ignored issues
show
Bug introduced by Antonio J. García Lagar
The class Whoops\Handler\XmlResponseHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
169
            return $response->withHeader('Content-Type', 'text/xml');
170
        }
171
172
        if ($handler instanceof PlainTextHandler) {
0 ignored issues
show
Bug introduced by Antonio J. García Lagar
The class Whoops\Handler\PlainTextHandler does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
173
            return $response->withHeader('Content-Type', 'text/plain');
174
        }
175
176
        return $response;
177
    }
178
}
179