Passed
Push — dev ( aca482...6fd7cc )
by Nico
08:12
created

ErrorHandler::outputHandler()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 30
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 10.0876

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
eloc 18
c 1
b 1
f 0
nc 4
nop 0
dl 0
loc 30
ccs 7
cts 17
cp 0.4118
crap 10.0876
rs 9.3554
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Stu\Config;
6
7
use Doctrine\DBAL\Connection;
8
use Monolog\Handler\StreamHandler;
9
use Monolog\Logger;
10
use Stu\Component\Logging\GameRequest\GameRequestSaverInterface;
11
use Stu\Lib\SessionInterface;
12
use Stu\Module\Config\StuConfigInterface;
13
use Stu\Module\Control\GameControllerInterface;
14
use Throwable;
15
use Whoops\Handler\PlainTextHandler;
16
use Whoops\Handler\PrettyPageHandler;
17
use Whoops\Run;
18
use Whoops\Util\Misc;
19
20
/**
21
 * Registers the main error handler
22
 */
23
final class ErrorHandler
24
{
25
    private Connection $database;
26
27
    private GameRequestSaverInterface $gameRequestSaver;
28
29
    private GameControllerInterface $game;
30
31
    private StuConfigInterface $stuConfig;
32
33
    private SessionInterface $session;
34
35 1
    public function __construct(
36
        Connection $database,
37
        GameRequestSaverInterface $gameRequestSaver,
38
        GameControllerInterface $game,
39
        StuConfigInterface $stuConfig,
40
        SessionInterface $session
41
    ) {
42 1
        $this->database = $database;
43 1
        $this->gameRequestSaver = $gameRequestSaver;
44 1
        $this->game = $game;
45 1
        $this->stuConfig = $stuConfig;
46 1
        $this->session = $session;
47
    }
48
49 1
    public function register(): void
50
    {
51 1
        $this->setErrorReporting();
52
53 1
        $whoops = new Run();
54
55 1
        $whoops->appendHandler($this->outputHandler());
56 1
        $whoops->prependHandler($this->transactionHandler());
57 1
        $whoops->prependHandler($this->logfileHandler());
58
59 1
        $whoops->register();
60
    }
61
62 1
    private function outputHandler(): mixed
63
    {
64
65
        if (
66 1
            $this->stuConfig->getDebugSettings()->isDebugMode()
67 1
            || $this->isAdminUser()
68
        ) {
69
70 1
            if (Misc::isCommandLine()) {
71 1
                $handler = new PlainTextHandler();
72
            } else {
73
                $handler = new PrettyPageHandler();
74 1
                $handler->setPageTitle('Error - Star Trek Universe');
75
            }
76
        } else {
77
            if (Misc::isCommandLine()) {
78
                $handler = new PlainTextHandler();
79
            } else {
80
                $handler = function (): void {
81
82
                    echo str_replace(
83
                        '$REQUESTID',
84
                        $this->game->getGameRequestId(),
85
                        (string) file_get_contents(__DIR__ . '/../html/error.html')
86
                    );
87
                };
88
            }
89
        }
90
91 1
        return $handler;
92
    }
93
94 1
    private function transactionHandler(): callable
95
    {
96 1
        return function (): void {
97
98
            // end transaction if still active
99
            if ($this->database->isTransactionActive()) {
100
                $this->database->rollBack();
101
            }
102
103
            // save the game request
104
            $this->gameRequestSaver->save(
105
                $this->game->getGameRequest(),
106
                true
107
            );
108 1
        };
109
    }
110
111 1
    private function logfileHandler(): callable
112
    {
113 1
        $logger = new Logger('stu');
114 1
        $logger->pushHandler(
115 1
            new StreamHandler($this->stuConfig->getDebugSettings()->getLogfilePath())
116 1
        );
117
118 1
        return function (Throwable $e) use ($logger) {
119
            $logger->error(
120
                $e->getMessage(),
121
                [
122
                    'file' => $e->getFile(),
123
                    'line' => $e->getLine(),
124
                    'trace' => $e->getTrace()
125
                ]
126
            );
127 1
        };
128
    }
129
130 1
    private function setErrorReporting(): void
131
    {
132
        if (
133 1
            $this->stuConfig->getDebugSettings()->isDebugMode()
134 1
            || $this->isAdminUser()
135
        ) {
136 1
            error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
137
        } else {
138
            error_reporting(E_ERROR | E_WARNING | E_PARSE);
139
        }
140
    }
141
142
    private function isAdminUser(): bool
143
    {
144
        $isAdminUser = false;
145
146
        // load the session handler only if a session has been started
147
        if (session_id() !== '') {
148
149
            $user = $this->session->getUser();
150
151
            $isAdminUser = $user !== null
152
                && in_array(
153
                    $user->getId(),
154
                    $this->stuConfig->getGameSettings()->getAdminIds(),
155
                    true
156
                );
157
        }
158
159
        return $isAdminUser;
160
    }
161
}
162