From 1816514c24fec13020cb9684a88b638456821e35 Mon Sep 17 00:00:00 2001 From: Aleksandr Minenok Date: Wed, 12 Apr 2023 10:18:14 +0300 Subject: [PATCH] laravel 10 support and strict types --- composer.json | 82 ++++++++++++---------- phpunit.xml | 26 +++---- src/ApiException.php | 67 +++++------------- src/ApiExceptionsServiceProvider.php | 2 + src/BadRequestApiException.php | 8 +-- src/ConflictApiException.php | 8 +-- src/Contracts/DontReport.php | 5 +- src/Contracts/ShowsPrevious.php | 5 +- src/Contracts/ShowsTrace.php | 5 +- src/ExceptionHandlerTrait.php | 25 +++---- src/ForbiddenApiException.php | 8 +-- src/IdException.php | 20 +++--- src/InternalServerErrorApiException.php | 8 +-- src/LaravelExceptionHandler.php | 2 + src/LumenExceptionHandler.php | 31 -------- src/MethodNotAllowedApiException.php | 8 +-- src/NotFoundApiException.php | 8 +-- src/Support/MessageBag.php | 12 +--- src/Support/Request.php | 21 ++---- src/Support/Validator.php | 36 +--------- src/TooManyRequestsApiException.php | 26 +++---- src/UnauthorizedApiException.php | 8 +-- src/ValidationFailedApiException.php | 36 ++-------- tests/ApiExceptionsServiceProviderTest.php | 2 + tests/ExceptionsOutputTest.php | 6 +- tests/TestCase.php | 2 + 26 files changed, 162 insertions(+), 305 deletions(-) delete mode 100644 src/LumenExceptionHandler.php diff --git a/composer.json b/composer.json index 317a0f1..886a804 100644 --- a/composer.json +++ b/composer.json @@ -1,41 +1,47 @@ { - "name": "lanin/laravel-api-exceptions", - "description": "All in one solution for exception for JSON REST APIs on Laravel and Lumen.", - "keywords": ["laravel", "framework", "api", "exceptions", "json"], - "license": "MIT", - "authors": [ - { - "name": "Maxim Lanin", - "email": "max@lanin.me", - "homepage": "https://blog.lanin.me" - } - ], - "require": { - "php": "^7.2|^8.0", - "illuminate/support": "^7.0|^8.0|^9.0" - }, - "require-dev": { - "orchestra/testbench": "^5.0", - "phpunit/phpunit": "^8.0", - "mockery/mockery": "^1.0" - }, - "autoload": { - "psr-4": { - "Lanin\\Laravel\\ApiExceptions\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Lanin\\Laravel\\ApiExceptions\\Tests\\": "tests/" - } - }, - "minimum-stability": "dev", - "prefer-stable": true, - "extra": { - "laravel": { - "providers": [ - "Lanin\\Laravel\\ApiExceptions\\ApiExceptionsServiceProvider" - ] - } + "name": "lanin/laravel-api-exceptions", + "description": "All in one solution for exception for JSON REST APIs on Laravel and Lumen.", + "keywords": [ + "laravel", + "framework", + "api", + "exceptions", + "json" + ], + "license": "MIT", + "authors": [ + { + "name": "Maxim Lanin", + "email": "max@lanin.me", + "homepage": "https://blog.lanin.me" } + ], + "require": { + "php": ">=8.1", + "illuminate/support": "^10.0" + }, + "require-dev": { + "orchestra/testbench": "^8.3", + "phpunit/phpunit": ">=8.0", + "mockery/mockery": "^1.0" + }, + "autoload": { + "psr-4": { + "Lanin\\Laravel\\ApiExceptions\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Lanin\\Laravel\\ApiExceptions\\Tests\\": "tests/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "laravel": { + "providers": [ + "Lanin\\Laravel\\ApiExceptions\\ApiExceptionsServiceProvider" + ] + } + } } diff --git a/phpunit.xml b/phpunit.xml index f77dd9b..7a033de 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,22 +1,16 @@ - + + + + ./src/ + + ./tests/ - - - ./src/ - - - \ No newline at end of file + diff --git a/src/ApiException.php b/src/ApiException.php index 7e403d4..a6a39ad 100644 --- a/src/ApiException.php +++ b/src/ApiException.php @@ -1,5 +1,7 @@ headers = $headers; - + public function __construct( + int $statusCode = 0, + string $id = '', + string $message = '', + ?\Throwable $previous = null, + protected array $headers = [], + ) { parent::__construct($id, $message, $previous, $statusCode); } - /** - * Return headers array. - * - * @return array - */ - public function getHeaders() + public function getHeaders(): array { return $this->headers; } - /** - * Convert the object into something JSON serializable. - * - * @return array - */ - public function jsonSerialize() + public function jsonSerialize(): mixed { return $this->toArray(); } - /** - * Convert exception to JSON. - * - * @param int $options - * @return array - */ - public function toJson($options = 0) + public function toJson($options = 0): string { return json_encode($this->toArray()); } - /** - * Convert exception to array. - * - * @return array - */ - public function toArray() + public function toArray(): array { $e = $this; @@ -76,7 +51,7 @@ public function toArray() if ($e instanceof ApiException) { $meta = $this->getMeta(); - if (! empty($meta)) { + if (!empty($meta)) { $return['meta'] = $meta; } } @@ -88,20 +63,16 @@ public function toArray() return $return; } - /** - * Prepare exception for report. - * - * @return string - */ - public function toReport() + public function toReport(): self { return $this; } /** * Add extra info to the output. - * - * @return mixed */ - public function getMeta() {} + public function getMeta(): array + { + return []; + } } diff --git a/src/ApiExceptionsServiceProvider.php b/src/ApiExceptionsServiceProvider.php index fd995f9..575b197 100644 --- a/src/ApiExceptionsServiceProvider.php +++ b/src/ApiExceptionsServiceProvider.php @@ -1,5 +1,7 @@ toReport() : $e); } @@ -27,9 +27,8 @@ public function report(\Throwable $e) /** * Render an exception into an HTTP response. * - * @param \Illuminate\Http\Request $request - * @param \Throwable $e - * @return \Illuminate\Http\Response + * @param Request $request + * @return JsonResponse */ public function render($request, \Throwable $e) { @@ -42,11 +41,8 @@ public function render($request, \Throwable $e) /** * Define exception. - * - * @param \Throwable $e - * @return ApiException */ - protected function resolveException(\Throwable $e) + protected function resolveException(\Throwable $e): ApiException { switch (true) { case $e instanceof ApiException: @@ -77,11 +73,8 @@ protected function resolveException(\Throwable $e) /** * Format error message for API response. - * - * @param ApiException $exception - * @return mixed */ - protected function formatApiResponse(ApiException $exception) + protected function formatApiResponse(ApiException $exception): array { return $exception->toArray(); } diff --git a/src/ForbiddenApiException.php b/src/ForbiddenApiException.php index e1d71a8..40eee68 100644 --- a/src/ForbiddenApiException.php +++ b/src/ForbiddenApiException.php @@ -1,16 +1,14 @@ id = $id; parent::__construct($message, $code, $previous); @@ -22,7 +20,7 @@ public function __construct($id = '', $message = '', ?\Throwable $previous = nul /** * @return string */ - public function getId() + public function getId(): string { return $this->id; } diff --git a/src/InternalServerErrorApiException.php b/src/InternalServerErrorApiException.php index 0fd9dbf..d465295 100644 --- a/src/InternalServerErrorApiException.php +++ b/src/InternalServerErrorApiException.php @@ -1,5 +1,7 @@ container->call([$this, 'rules']); return $this->only(array_keys($rules)); } - /** - * Determine if the user is authorized to make this request. - * - * @return bool - */ - public function authorize() + public function authorize(): bool { return true; } - /** - * Handle a failed validation attempt. - * - * @param Validator $validator - * @throws ValidationFailedApiException - */ - protected function failedValidation(Validator $validator) + protected function failedValidation(Validator $validator): void { throw new ValidationFailedApiException($validator->getMessageBag()->toArray()); } diff --git a/src/Support/Validator.php b/src/Support/Validator.php index 0849ed8..9e2baa0 100644 --- a/src/Support/Validator.php +++ b/src/Support/Validator.php @@ -1,47 +1,17 @@ getMessage($attribute, $rule); - $message = $this->doReplacements($message, $attribute, $rule, $parameters); - - $return = [ - 'rule' => Str::snake($rule), - 'message' => $message, - ]; - - if (! empty($parameters) && ! in_array($rule, ['Unique', 'Exists'])) { - $return['parameters'] = $parameters; - } - - // Return rule with attribute type for complex size validators - if (in_array($rule, $this->sizeRules)) { - $return['rule'] .= '.' . $this->getAttributeType($attribute); - } - - $this->messages->add($attribute, $return); - } - /** * Determine if the data passes the validation rules. - * - * @return bool */ - public function passes() + public function passes(): bool { $this->messages = new MessageBag; diff --git a/src/TooManyRequestsApiException.php b/src/TooManyRequestsApiException.php index 4c59eb3..4c81349 100644 --- a/src/TooManyRequestsApiException.php +++ b/src/TooManyRequestsApiException.php @@ -1,28 +1,26 @@ retryAfter = $retryAfter; - + public function __construct(protected ?int $retryAfter = null, + array $headers = [], + string $message = '', + ?\Throwable $previous = null, + ) { if (empty($message)) { - $message = 'Rate limit exceed.'; + $message = 'Rate limit exceeded.'; } if ($retryAfter) { @@ -32,17 +30,13 @@ public function __construct($retryAfter = null, $headers = [], $message = '', ? parent::__construct(429, 'too_many_requests', $message, $previous, $headers); } - /** - * Add extra info to the output. - * - * @return mixed - */ - public function getMeta() + public function getMeta(): array { if ($this->retryAfter) { return [ 'retry_after' => $this->retryAfter ]; } + return []; } } diff --git a/src/UnauthorizedApiException.php b/src/UnauthorizedApiException.php index 1b2daa6..c15dcc5 100644 --- a/src/UnauthorizedApiException.php +++ b/src/UnauthorizedApiException.php @@ -1,16 +1,14 @@ errors = $errors; @@ -29,22 +19,15 @@ public function __construct(array $errors, $message = '', ?\Throwable $previous parent::__construct(422, 'validation_failed', $message, $previous); } - /** - * Get array of errors - * - * @return array - */ - public function getErrors() + public function getErrors(): array { return $this->errors; } - + /** * Convert and return validations errors in native Laravel way. - * - * @return array */ - public function getNativeErrors() + public function getNativeErrors(): array { $return = []; @@ -58,12 +41,7 @@ public function getNativeErrors() return $return; } - /** - * Add extra info to the output. - * - * @return mixed - */ - public function getMeta() + public function getMeta(): array { return [ 'errors' => $this->getErrors(), diff --git a/tests/ApiExceptionsServiceProviderTest.php b/tests/ApiExceptionsServiceProviderTest.php index da0658b..0ade21a 100644 --- a/tests/ApiExceptionsServiceProviderTest.php +++ b/tests/ApiExceptionsServiceProviderTest.php @@ -1,5 +1,7 @@