Failed Conditions
Pull Request — master (#2127)
by Janko
10:05
created

ErrorHandler::register()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

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