Skip to content

Commit 5bc372c

Browse files
authored
Merge pull request #59 from blitz-php/devs
chore: refactorisation du gestionnaire d'exception
2 parents 16bc55b + 2c70bf6 commit 5bc372c

5 files changed

Lines changed: 132 additions & 144 deletions

File tree

phpstan-baseline.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,6 @@
7373
'count' => 1,
7474
'path' => __DIR__ . '/src/Controllers/RestController.php',
7575
];
76-
$ignoreErrors[] = [
77-
// identifier: class.notFound
78-
'message' => '#^Call to static method make\\(\\) on an unknown class Spatie\\\\Ignition\\\\Ignition\\.$#',
79-
'count' => 1,
80-
'path' => __DIR__ . '/src/Debug/Debugger.php',
81-
];
8276
$ignoreErrors[] = [
8377
// identifier: booleanNot.alwaysFalse
8478
'message' => '#^Negated boolean expression is always false\\.$#',

spec/system/framework/Cli/Commands/ClearLog.spec.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
$date = $this->date;
2424
$path = STORAGE_PATH . 'logs' . DS . "log-{$date}.log";
2525

26+
if (! is_dir($dir = dirname($path))) {
27+
@mkdir($dir, 0777, true);
28+
}
29+
2630
// creer 10 faux ficher de log
2731
for ($i = 0; $i < 10; $i++) {
2832
$newDate = date('Y-m-d', strtotime("+1 year -{$i} day"));

src/Core/Application.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace BlitzPHP\Core;
1313

1414
use BlitzPHP\Container\Services;
15-
use BlitzPHP\Debug\Debugger;
15+
use BlitzPHP\Debug\ExceptionManager;
1616
use BlitzPHP\Event\EventDiscover;
1717
use BlitzPHP\Exceptions\ExceptionInterface;
1818
use BlitzPHP\Router\Dispatcher;
@@ -67,7 +67,7 @@ public function init(): self
6767
/**
6868
* Lance la capture des exceptions et erreurs
6969
*/
70-
Debugger::init();
70+
service(ExceptionManager::class)->register();
7171

7272
/**
7373
* Initialisation du gestionnaire d'evenement

src/Debug/Debugger.php

Lines changed: 0 additions & 64 deletions
This file was deleted.

src/Debug/ExceptionManager.php

Lines changed: 126 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -27,117 +27,149 @@
2727
use Whoops\Util\Misc;
2828

2929
/**
30-
* Gestionnaire d'exceptions
30+
* Capture et affiche les erreurs et exceptions via whoops
31+
*
32+
* Necessite l'instalation de `flip/whoops`
3133
*/
3234
class ExceptionManager
3335
{
3436
/**
35-
* Gestionnaire d'exceptions de type http (404, 500) qui peuvent avoir une page d'erreur personnalisée.
37+
* Gestionnaire d'exception (instance Whoops)
38+
*/
39+
private ?Run $debugger = null;
40+
41+
/**
42+
* Configuration du gestionnaire d'exception
43+
*/
44+
private object $config;
45+
46+
public function __construct()
47+
{
48+
if (class_exists(Run::class)) {
49+
$this->debugger = new Run();
50+
$this->config = (object) config('exceptions');
51+
}
52+
}
53+
54+
/**
55+
* Demarre le processus
3656
*/
37-
public static function registerHttpErrors(Run $debugger, array $config): Run
57+
public function register(): void
3858
{
39-
return $debugger->pushHandler(static function (Throwable $exception, InspectorInterface $inspector, RunInterface $run) use ($config): int {
40-
$exception = self::prepareException($exception);
59+
if (! $this->debugger) {
60+
return;
61+
}
4162

63+
$this->registerWhoopsHandler()
64+
->registerHttpErrorsHandler()
65+
->registerAppHandlers();
66+
67+
$this->debugger->register();
68+
}
69+
70+
/**
71+
* Enregistre les gestionnaires d'exception spécifiques à l'application.
72+
*
73+
* Cette méthode parcourt les gestionnaires configurés et les ajoute au débogueur.
74+
* Elle prend en charge à la fois les gestionnaires callable et les noms de classe sous forme de chaîne qui peuvent être instanciés.
75+
*/
76+
private function registerAppHandlers(): self
77+
{
78+
foreach ($this->config->handlers as $handler) {
79+
if (is_callable($handler)) {
80+
$this->debugger->pushHandler($handler);
81+
} elseif (is_string($handler) && class_exists($handler)) {
82+
$class = service('container')->make($handler);
83+
if (is_callable($class) || $class instanceof HandlerInterface) {
84+
$this->debugger->pushHandler($class);
85+
}
86+
}
87+
}
88+
89+
return $this;
90+
}
91+
92+
/**
93+
* Enregistre un gestionnaire pour les erreurs HTTP.
94+
*
95+
* Cette méthode met en place un gestionnaire d'erreurs personnalisé qui traite les exceptions,
96+
* les consigne si elle est configurée, et tente d'afficher les vues d'erreur appropriées.
97+
* Elle gère les codes d'état HTTP, la journalisation et les vues d'erreur personnalisées.
98+
*/
99+
private function registerHttpErrorsHandler(): self
100+
{
101+
$this->debugger->pushHandler(function (Throwable $exception, InspectorInterface $inspector, RunInterface $run): int {
102+
$exception = $this->prepareException($exception);
42103
$exception_code = $exception->getCode();
104+
43105
if ($exception_code >= 400 && $exception_code < 600) {
44106
$run->sendHttpCode($exception_code);
45107
}
46108

47-
if (true === $config['log'] && ! in_array($exception->getCode(), $config['ignore_codes'], true)) {
109+
if (true === $this->config->log && ! in_array($exception_code, $this->config->ignore_codes, true)) {
48110
service('logger')->error($exception);
49111
}
50112

51-
if (is_dir($config['error_view_path'])) {
52-
$files = array_map(static fn (SplFileInfo $file) => $file->getFilenameWithoutExtension(), service('fs')->files($config['error_view_path']));
113+
if (is_dir($this->config->error_view_path)) {
114+
$files = array_map(static fn (SplFileInfo $file) => $file->getFilenameWithoutExtension(), service('fs')->files($this->config->error_view_path));
53115
} else {
54116
$files = [];
55117
}
56118

57-
if (in_array((string) $exception->getCode(), $files, true)) {
58-
$view = new View();
59-
$view->setAdapter(config('view.active_adapter', 'native'), ['view_path' => $config['error_view_path']])
60-
->display((string) $exception->getCode())
61-
->setData(['message' => $exception->getMessage()])
62-
->render();
119+
$files = collect($files)->flip()->only($exception_code, is_online() ? 'production' : '')->flip()->all();
63120

64-
return Handler::QUIT;
65-
}
66-
if (in_array('production', $files, true) && is_online()) {
121+
if ($files !== []) {
67122
$view = new View();
68-
$view->setAdapter(config('view.active_adapter', 'native'), ['view_path_locator' => $config['error_view_path']])
69-
->display('production')
123+
124+
$view->setAdapter(config('view.active_adapter', 'native'), ['view_path' => $this->config->error_view_path])
125+
->first($files, ['message' => $exception->getMessage()])
70126
->render();
71127

72128
return Handler::QUIT;
73129
}
74130

75131
return Handler::DONE;
76132
});
77-
}
78-
79-
/**
80-
* Gestionnaire d'applications fournis par le developpeur.
81-
*/
82-
public static function registerAppHandlers(Run $debugger, array $config): Run
83-
{
84-
foreach ($config['handlers'] ?? [] as $handler) {
85-
if (is_callable($handler)) {
86-
$debugger->pushHandler($handler);
87-
} elseif (is_string($handler) && class_exists($handler)) {
88-
$class = service('container')->make($handler);
89-
if (is_callable($class) || $class instanceof HandlerInterface) {
90-
$debugger->pushHandler($class);
91-
}
92-
}
93-
}
94133

95-
return $debugger;
134+
return $this;
96135
}
97136

98137
/**
99-
* Gestionnaire d'erreurs globales whoops
138+
* Enregistre un gestionnaire de Whoops à des fins de débogage.
139+
*
140+
* Cette méthode met en place différents gestionnaires en fonction de l'environnement et des paramètres de configuration.
141+
* Elle vérifie la ligne de commande, l'état en ligne, les requêtes AJAX et les requêtes JSON.
142+
* En fonction des conditions, elle utilise PlainTextHandler, JsonResponseHandler ou PrettyPageHandler.
143+
*
144+
* Le PrettyPageHandler est configuré avec les paramètres de l'éditeur, le titre de la page, les chemins d'accès à l'application,
145+
* les données sur liste noire et les tables de données. Il gère également différents types de données pour les tables de données.
100146
*/
101-
public static function registerWhoopsHandler(Run $debugger, array $config): Run
147+
private function registerWhoopsHandler(): self
102148
{
103149
if (Misc::isCommandLine()) {
104-
$debugger->pushHandler(new PlainTextHandler());
105-
}
106-
107-
if (! is_online()) {
108-
if (Misc::isAjaxRequest() || service('request')->isJson()) {
109-
$debugger->pushHandler(new JsonResponseHandler());
110-
} else {
111-
$handler = new PrettyPageHandler();
150+
$this->debugger->pushHandler(new PlainTextHandler(service('logger')));
112151

113-
$handler->setEditor($config['editor'] ?: PrettyPageHandler::EDITOR_VSCODE);
114-
$handler->setPageTitle($config['title'] ?: $handler->getPageTitle());
115-
$handler->setApplicationRootPath(APP_PATH);
116-
$handler->setApplicationPaths([APP_PATH, SYST_PATH, VENDOR_PATH]);
152+
return $this;
153+
}
117154

118-
$handler = self::setBlacklist($handler, $config['blacklist']);
155+
if (is_online()) {
156+
return $this;
157+
}
119158

120-
foreach ($config['data'] as $label => $data) {
121-
if (is_array($data)) {
122-
$handler->addDataTable($label, $data);
123-
} elseif (is_callable($data)) {
124-
$handler->addDataTableCallback($label, $data);
125-
}
126-
}
159+
if (Misc::isAjaxRequest() || service('request')->isJson()) {
160+
$this->debugger->pushHandler(new JsonResponseHandler());
127161

128-
$debugger->pushHandler($handler);
129-
}
162+
return $this;
130163
}
131164

132-
return $debugger;
133-
}
165+
$handler = new PrettyPageHandler();
134166

135-
/**
136-
* Enregistre les elements blacklisté dans l'affichage du rapport d'erreur
137-
*/
138-
private static function setBlacklist(PrettyPageHandler $handler, array $blacklists): PrettyPageHandler
139-
{
140-
foreach ($blacklists as $blacklist) {
167+
$handler->handleUnconditionally(true);
168+
$handler->setEditor($this->config->editor ?: PrettyPageHandler::EDITOR_VSCODE);
169+
$handler->setPageTitle($this->config->title ?: $handler->getPageTitle());
170+
$handler->setApplicationPaths($this->getApplicationPaths());
171+
172+
foreach ($this->config->blacklist as $blacklist) {
141173
[$name, $key] = explode('/', $blacklist) + [1 => '*'];
142174

143175
if ($name[0] !== '_') {
@@ -168,18 +200,40 @@ private static function setBlacklist(PrettyPageHandler $handler, array $blacklis
168200
}
169201
}
170202

171-
return $handler;
203+
foreach ($this->config->data as $label => $data) {
204+
if (is_array($data)) {
205+
$handler->addDataTable($label, $data);
206+
} elseif (is_callable($data)) {
207+
$handler->addDataTableCallback($label, $data);
208+
}
209+
}
210+
211+
$this->debugger->pushHandler($handler);
212+
213+
return $this;
172214
}
173215

174216
/**
175-
* Prepare exception for rendering.
217+
* Préparer l'exception pour le rendu.
176218
*/
177219
private static function prepareException(Throwable $e): Throwable
178220
{
179221
if ($e instanceof TokenMismatchException) {
180-
$e = new HttpException($e->getMessage(), 419, $e);
222+
return new HttpException($e->getMessage(), 419, $e);
181223
}
182224

183225
return $e;
184226
}
227+
228+
/**
229+
* Récupère les chemins d'accès à l'application.
230+
*/
231+
private function getApplicationPaths(): array
232+
{
233+
return collect(service('fs')->directories(base_path()))
234+
->flip()
235+
->except(base_path('vendor'))
236+
->flip()
237+
->all();
238+
}
185239
}

0 commit comments

Comments
 (0)