Passed
Push — master ( 4c294d...73245e )
by Nico
31:23
created

ErrorHandler::transactionHandler()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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