mirror of
https://github.com/flarum/framework.git
synced 2025-05-16 03:02:31 +08:00
Wire up new error handling stack
This commit is contained in:
parent
2c231aa475
commit
2f174edfd0
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Foundation\ErrorHandling\ExceptionHandler;
|
||||||
|
|
||||||
|
use Flarum\Foundation\ErrorHandling\HandledError;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class IlluminateValidationExceptionHandler
|
||||||
|
{
|
||||||
|
public function handle(ValidationException $e): HandledError
|
||||||
|
{
|
||||||
|
return (new HandledError(
|
||||||
|
$e, 'validation_error', 422
|
||||||
|
))->withDetails($this->errorDetails($e));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function errorDetails(ValidationException $e): array
|
||||||
|
{
|
||||||
|
$errors = $e->errors();
|
||||||
|
|
||||||
|
return array_map(function ($field, $messages) {
|
||||||
|
return [
|
||||||
|
'detail' => implode("\n", $messages),
|
||||||
|
'source' => ['pointer' => "/data/attributes/$field"]
|
||||||
|
];
|
||||||
|
}, array_keys($errors), $errors);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Foundation\ErrorHandling\ExceptionHandler;
|
||||||
|
|
||||||
|
use Flarum\Foundation\ErrorHandling\HandledError;
|
||||||
|
use Flarum\Foundation\ValidationException;
|
||||||
|
|
||||||
|
class ValidationExceptionHandler
|
||||||
|
{
|
||||||
|
public function handle(ValidationException $e)
|
||||||
|
{
|
||||||
|
return (new HandledError(
|
||||||
|
$e, 'validation_error', 422
|
||||||
|
))->withDetails(array_merge(
|
||||||
|
$this->buildDetails($e->getAttributes(), '/data/attributes'),
|
||||||
|
$this->buildDetails($e->getRelationships(), '/data/relationships')
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildDetails(array $messages, $pointer): array
|
||||||
|
{
|
||||||
|
return array_map(function ($path, $detail) use ($pointer) {
|
||||||
|
return [
|
||||||
|
'detail' => $detail,
|
||||||
|
'source' => ['pointer' => $pointer.'/'.$path]
|
||||||
|
];
|
||||||
|
}, array_keys($messages), $messages);
|
||||||
|
}
|
||||||
|
}
|
76
src/Foundation/ErrorServiceProvider.php
Normal file
76
src/Foundation/ErrorServiceProvider.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Foundation;
|
||||||
|
|
||||||
|
use Flarum\Foundation\ErrorHandling\ExceptionHandler;
|
||||||
|
use Flarum\Foundation\ErrorHandling\LogReporter;
|
||||||
|
use Flarum\Foundation\ErrorHandling\Registry;
|
||||||
|
use Flarum\Foundation\ErrorHandling\Reporter;
|
||||||
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
|
use Illuminate\Validation\ValidationException as IlluminateValidationException;
|
||||||
|
use Tobscure\JsonApi\Exception\InvalidParameterException;
|
||||||
|
|
||||||
|
class ErrorServiceProvider extends AbstractServiceProvider
|
||||||
|
{
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
$this->app->singleton('flarum.error.statuses', function () {
|
||||||
|
return [
|
||||||
|
// 400 Bad Request
|
||||||
|
'csrf_token_mismatch' => 400,
|
||||||
|
'invalid_parameter' => 400,
|
||||||
|
|
||||||
|
// 401 Unauthorized
|
||||||
|
'invalid_access_token' => 401,
|
||||||
|
|
||||||
|
// 403 Forbidden
|
||||||
|
'forbidden' => 403,
|
||||||
|
'invalid_confirmation_token' => 403,
|
||||||
|
'permission_denied' => 403,
|
||||||
|
|
||||||
|
// 404 Not Found
|
||||||
|
'model_not_found' => 404,
|
||||||
|
'route_not_found' => 404,
|
||||||
|
|
||||||
|
// 405 Method Not Allowed
|
||||||
|
'method_not_allowed' => 405,
|
||||||
|
|
||||||
|
// 429 Too Many Requests
|
||||||
|
'too_many_requests' => 429,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->app->singleton('flarum.error.classes', function () {
|
||||||
|
return [
|
||||||
|
InvalidParameterException::class => 'invalid_parameter',
|
||||||
|
ModelNotFoundException::class => 'model_not_found',
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->app->singleton('flarum.error.handlers', function () {
|
||||||
|
return [
|
||||||
|
IlluminateValidationException::class => ExceptionHandler\IlluminateValidationExceptionHandler::class,
|
||||||
|
ValidationException::class => ExceptionHandler\ValidationExceptionHandler::class,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->app->singleton(Registry::class, function () {
|
||||||
|
return new Registry(
|
||||||
|
$this->app->make('flarum.error.statuses'),
|
||||||
|
$this->app->make('flarum.error.classes'),
|
||||||
|
$this->app->make('flarum.error.handlers')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->app->singleton(Reporter::class, LogReporter::class);
|
||||||
|
}
|
||||||
|
}
|
@ -115,6 +115,7 @@ class InstalledSite implements SiteInterface
|
|||||||
$laravel->register(DatabaseServiceProvider::class);
|
$laravel->register(DatabaseServiceProvider::class);
|
||||||
$laravel->register(DiscussionServiceProvider::class);
|
$laravel->register(DiscussionServiceProvider::class);
|
||||||
$laravel->register(ExtensionServiceProvider::class);
|
$laravel->register(ExtensionServiceProvider::class);
|
||||||
|
$laravel->register(ErrorServiceProvider::class);
|
||||||
$laravel->register(FilesystemServiceProvider::class);
|
$laravel->register(FilesystemServiceProvider::class);
|
||||||
$laravel->register(FormatterServiceProvider::class);
|
$laravel->register(FormatterServiceProvider::class);
|
||||||
$laravel->register(ForumServiceProvider::class);
|
$laravel->register(ForumServiceProvider::class);
|
||||||
|
@ -67,6 +67,7 @@ class UninstalledSite implements SiteInterface
|
|||||||
|
|
||||||
$this->registerLogger($laravel);
|
$this->registerLogger($laravel);
|
||||||
|
|
||||||
|
$laravel->register(ErrorServiceProvider::class);
|
||||||
$laravel->register(LocaleServiceProvider::class);
|
$laravel->register(LocaleServiceProvider::class);
|
||||||
$laravel->register(FilesystemServiceProvider::class);
|
$laravel->register(FilesystemServiceProvider::class);
|
||||||
$laravel->register(SessionServiceProvider::class);
|
$laravel->register(SessionServiceProvider::class);
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Tests\unit\Foundation\ErrorHandling\ExceptionHandler;
|
||||||
|
|
||||||
|
use Flarum\Foundation\ErrorHandling\ExceptionHandler\IlluminateValidationExceptionHandler;
|
||||||
|
use Illuminate\Translation\ArrayLoader;
|
||||||
|
use Illuminate\Translation\Translator;
|
||||||
|
use Illuminate\Validation\Factory;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class IlluminateValidationExceptionHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
private $handler;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->handler = new IlluminateValidationExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_it_creates_the_desired_output()
|
||||||
|
{
|
||||||
|
$exception = new ValidationException($this->makeValidator(['foo' => ''], ['foo' => 'required']));
|
||||||
|
|
||||||
|
$error = $this->handler->handle($exception);
|
||||||
|
|
||||||
|
$this->assertEquals(422, $error->getStatusCode());
|
||||||
|
$this->assertEquals('validation_error', $error->getType());
|
||||||
|
$this->assertEquals([
|
||||||
|
[
|
||||||
|
'detail' => 'validation.required',
|
||||||
|
'source' => ['pointer' => '/data/attributes/foo']
|
||||||
|
]
|
||||||
|
], $error->getDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function makeValidator($data = [], $rules = [])
|
||||||
|
{
|
||||||
|
$translator = new Translator(new ArrayLoader(), 'en');
|
||||||
|
$factory = new Factory($translator);
|
||||||
|
|
||||||
|
return $factory->make($data, $rules);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Flarum.
|
||||||
|
*
|
||||||
|
* (c) Toby Zerner <toby.zerner@gmail.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Flarum\Tests\unit\Foundation\ErrorHandling\ExceptionHandler;
|
||||||
|
|
||||||
|
use Flarum\Foundation\ErrorHandling\ExceptionHandler\ValidationExceptionHandler;
|
||||||
|
use Flarum\Foundation\ValidationException;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ValidationExceptionHandlerTest extends TestCase
|
||||||
|
{
|
||||||
|
private $handler;
|
||||||
|
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
$this->handler = new ValidationExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_managing_exceptions()
|
||||||
|
{
|
||||||
|
$error = $this->handler->handle(new ValidationException(
|
||||||
|
['foo' => 'Attribute error'],
|
||||||
|
['bar' => 'Relationship error']
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->assertEquals(422, $error->getStatusCode());
|
||||||
|
$this->assertEquals('validation_error', $error->getType());
|
||||||
|
$this->assertEquals([
|
||||||
|
[
|
||||||
|
'detail' => 'Attribute error',
|
||||||
|
'source' => ['pointer' => '/data/attributes/foo']
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'detail' => 'Relationship error',
|
||||||
|
'source' => ['pointer' => '/data/relationships/bar']
|
||||||
|
]
|
||||||
|
], $error->getDetails());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user