• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / typo3-solver / 8562357037

04 Apr 2024 10:58PM UTC coverage: 87.107%. Remained the same
8562357037

Pull #221

github

web-flow
[TASK] Update css-loader to v7

| datasource | package    | from   | to    |
| ---------- | ---------- | ------ | ----- |
| npm        | css-loader | 6.11.0 | 7.0.0 |
Pull Request #221: [TASK] Update css-loader to v7

858 of 985 relevant lines covered (87.11%)

6.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/Classes/Error/AiSolverExceptionHandler.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "solver".
7
 *
8
 * Copyright (C) 2024 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\Typo3Solver\Error;
25

26
use EliasHaeussler\Typo3Solver\Authentication;
27
use EliasHaeussler\Typo3Solver\Cache;
28
use EliasHaeussler\Typo3Solver\Configuration;
29
use EliasHaeussler\Typo3Solver\Exception;
30
use EliasHaeussler\Typo3Solver\Formatter;
31
use EliasHaeussler\Typo3Solver\Middleware;
32
use EliasHaeussler\Typo3Solver\ProblemSolving;
33
use EliasHaeussler\Typo3Solver\Utility;
34
use EliasHaeussler\Typo3Solver\View;
35
use GuzzleHttp\Client;
36
use GuzzleHttp\HandlerStack;
37
use GuzzleHttp\RequestOptions;
38
use Throwable;
39
use TYPO3\CMS\Core;
40

41
/**
42
 * AiSolverExceptionHandler.
43
 *
44
 * @author Elias Häußler <elias@haeussler.dev>
45
 * @license GPL-2.0-or-later
46
 */
47
final class AiSolverExceptionHandler extends Core\Error\DebugExceptionHandler
48
{
49
    private readonly Client $client;
50
    private readonly Configuration\Configuration $configuration;
51
    private readonly Formatter\Message\ExceptionFormatter $exceptionFormatter;
52
    private readonly Cache\ExceptionsCache $exceptionsCache;
53
    private readonly Cache\SolutionsCache $solutionsCache;
54
    private readonly Formatter\CliFormatter $cliFormatter;
55
    private readonly Formatter\WebFormatter $webFormatter;
56

57
    public function __construct()
×
58
    {
59
        parent::__construct();
×
60

61
        $renderer = new View\TemplateRenderer();
×
62

63
        $this->client = $this->createClient();
×
64
        $this->configuration = new Configuration\Configuration();
×
65
        $this->exceptionFormatter = new Formatter\Message\ExceptionFormatter($renderer);
×
66
        $this->exceptionsCache = new Cache\ExceptionsCache();
×
67
        $this->solutionsCache = new Cache\SolutionsCache();
×
68
        $this->cliFormatter = new Formatter\CliFormatter($renderer);
×
69
        $this->webFormatter = new Formatter\WebFormatter(
×
70
            $this->exceptionsCache,
×
71
            $renderer,
×
72
            new Authentication\StreamAuthentication(),
×
73
        );
×
74
    }
75

76
    public function echoExceptionCLI(Throwable $exception): void
×
77
    {
78
        try {
79
            $solver = new ProblemSolving\Solver($this->configuration, $this->cliFormatter);
×
80
            $solution = $solver->solve($exception);
×
81

82
            if ($solution !== null) {
×
83
                echo $solution;
×
84
            }
85
        } catch (Exception\UnableToSolveException) {
×
86
            // Intended fallthrough.
87
        }
88

89
        parent::echoExceptionCLI($exception);
×
90
    }
91

92
    protected function getContent(Throwable $throwable): string
×
93
    {
94
        $content = parent::getContent($throwable);
×
95
        $serverRequest = Utility\HttpUtility::getServerRequest();
×
96

97
        // Early return if solver is disabled
98
        if ($serverRequest->getQueryParams()['disableSolver'] ?? false) {
×
99
            return $content;
×
100
        }
101

102
        $solutionProvider = $this->configuration->getProvider();
×
103

104
        // Use solution stream if possible
105
        if ($solutionProvider->canBeUsed($throwable) && $this->isStreamedResponseSupported()) {
×
106
            $this->exceptionsCache->set($throwable);
×
107

108
            $solutionProvider = new ProblemSolving\Solution\Provider\DelegatingCacheSolutionProvider(
×
109
                $this->solutionsCache,
×
110
                $solutionProvider,
×
111
            );
×
112
        }
113

114
        try {
115
            $solver = new ProblemSolving\Solver($this->configuration, $this->webFormatter, $solutionProvider);
×
116
            $solution = $solver->solve($throwable);
×
117

118
            if ($solution !== null) {
×
119
                $solution .= $this->webFormatter->getAdditionalScripts();
×
120
            }
121
        } catch (Throwable $exception) {
×
122
            $solution = $this->exceptionFormatter->format($exception);
×
123
        }
124

125
        if ($solution === null) {
×
126
            return $content;
×
127
        }
128

129
        return Utility\StringUtility::replaceFirstOccurrence(
×
130
            '<div class="trace">',
×
131
            $solution . '<div class="trace">',
×
132
            $content,
×
133
        );
×
134
    }
135

136
    protected function getStylesheet(): string
×
137
    {
138
        return parent::getStylesheet() . $this->webFormatter->getAdditionalStyles();
×
139
    }
140

141
    private function isStreamedResponseSupported(): bool
×
142
    {
143
        $serverRequest = Utility\HttpUtility::getServerRequest();
×
144
        $pingUri = $serverRequest->getUri()
×
145
            ->withPath(Middleware\PingMiddleware::ROUTE_PATH)
×
146
            ->withQuery('disableSolver=1')
×
147
        ;
×
148
        $pingResponse = $this->client->request('GET', $pingUri, [
×
149
            RequestOptions::HEADERS => [
×
150
                'Accept' => 'text/event-stream',
×
151
            ],
×
152
        ]);
×
153

154
        return $pingResponse->getStatusCode() === 200;
×
155
    }
156

157
    private function createClient(): Client
×
158
    {
159
        $handler = HandlerStack::create();
×
160
        $handler->remove('http_errors');
×
161

162
        return new Client(['handler' => $handler]);
×
163
    }
164
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc