Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
Handler
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
9 / 9
17
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 register
n/a
0 / 0
n/a
0 / 0
2
 errorHandler
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 exceptionHandler
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
4
 terminateApplicationImmediately
n/a
0 / 0
n/a
0 / 0
1
 getEnvironment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setEnvironment
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getHandler
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 setHandler
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRequest
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace Engelsystem\Exceptions;
6
7use Engelsystem\Environment;
8use Engelsystem\Exceptions\Handlers\HandlerInterface;
9use Engelsystem\Exceptions\Handlers\Legacy;
10use Engelsystem\Http\Request;
11use ErrorException;
12use Throwable;
13
14class Handler
15{
16    /** @var HandlerInterface[] */
17    protected array $handler = [];
18
19    protected ?Request $request = null;
20
21    /**
22     * Handler constructor.
23     *
24     * @param Environment $environment prod|dev
25     */
26    public function __construct(protected Environment $environment = Environment::PRODUCTION)
27    {
28    }
29
30    /**
31     * Activate the error handler
32     * @codeCoverageIgnore
33     */
34    public function register(): void
35    {
36        if (defined('PHPUNIT_COMPOSER_INSTALL')) {
37            return;
38        }
39
40        set_error_handler([$this, 'errorHandler']);
41        set_exception_handler([$this, 'exceptionHandler']);
42    }
43
44    public function errorHandler(int $errorNumber, string $message, string $file, int $line): bool
45    {
46        $handleLevel = $this->environment == Environment::DEVELOPMENT
47            ? E_ALL
48            : E_RECOVERABLE_ERROR | E_COMPILE_ERROR;
49        // If error level should be intercepted or ignored (like warnings in prod)
50        $shouldHandle = (bool) ($errorNumber & $handleLevel);
51
52        $exception = new ErrorException($message, 0, $errorNumber, $file, $line);
53        $this->exceptionHandler($exception, $shouldHandle);
54
55        return $shouldHandle;
56    }
57
58    public function exceptionHandler(Throwable $e, bool $showError = true): string
59    {
60        if (!$this->request instanceof Request) {
61            $this->request = new Request();
62        }
63
64        $handler = $this->handler[$this->environment->value] ?? new Legacy();
65        $handler->report($e);
66        ob_start();
67        $handler->render($this->request, $e);
68
69        if (!$showError) {
70            $output = ob_get_contents();
71            ob_end_clean();
72            return $output;
73        }
74
75        if (!headers_sent()) {
76            // @codeCoverageIgnoreStart
77            http_response_code(500);
78            // @codeCoverageIgnoreEnd
79        }
80
81        ob_end_flush();
82
83        $this->terminateApplicationImmediately();
84
85        return '';
86    }
87
88    /**
89     * Exit the application
90     *
91     * @codeCoverageIgnore
92     */
93    protected function terminateApplicationImmediately(string $message = ''): void
94    {
95        echo $message;
96        die(1);
97    }
98
99    public function getEnvironment(): Environment
100    {
101        return $this->environment;
102    }
103
104    public function setEnvironment(Environment $environment): void
105    {
106        $this->environment = $environment;
107    }
108
109    /**
110     * @return HandlerInterface|HandlerInterface[]
111     */
112    public function getHandler(?Environment $environment = null): HandlerInterface|array
113    {
114        if (!is_null($environment)) {
115            return $this->handler[$environment->value];
116        }
117
118        return $this->handler;
119    }
120
121    public function setHandler(Environment $environment, HandlerInterface $handler): void
122    {
123        $this->handler[$environment->value] = $handler;
124    }
125
126    public function getRequest(): Request
127    {
128        return $this->request;
129    }
130
131    public function setRequest(Request $request): void
132    {
133        $this->request = $request;
134    }
135}