diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 0626077..a94487b 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- php-version: ['8.1', '8.2', '8.3']
+ php-version: ['8.1', '8.2', '8.3', '8.4']
steps:
- uses: actions/checkout@v1
diff --git a/composer.json b/composer.json
index 0782e89..227e861 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,10 @@
{
- "name": "phauthentic/error-response",
+ "name": "phauthentic/problem-details",
"type": "library",
"require-dev": {
+ "infection/infection": "^0.29.10",
"nyholm/psr7": "^1.8",
+ "phpmd/phpmd": "^2.15",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.5.0",
"squizlabs/php_codesniffer": "^3.9"
@@ -10,12 +12,12 @@
"license": "MIT",
"autoload": {
"psr-4": {
- "Phauthentic\\ErrorResponse\\": "src/"
+ "Phauthentic\\ProblemDetails\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
- "Phauthentic\\ErrorResponse\\Tests\\": "tests/"
+ "Phauthentic\\ProblemDetails\\Tests\\": "tests/"
}
},
"authors": [
@@ -31,6 +33,38 @@
},
"config": {
"sort-packages": true,
- "bin-dir": "bin"
+ "bin-dir": "bin",
+ "allow-plugins": {
+ "infection/extension-installer": true
+ }
+ },
+ "scripts": {
+ "test": [
+ "phpunit"
+ ],
+ "infection": [
+ "infection"
+ ],
+ "test-coverage": [
+ "phpunit --coverage-text"
+ ],
+ "test-coverage-html": [
+ "phpunit --coverage-html tmp/coverage/"
+ ],
+ "cscheck": [
+ "phpcs src/ tests/ -s"
+ ],
+ "csfix": [
+ "phpcbf src/ tests/"
+ ],
+ "analyze": [
+ "phpstan analyse src/"
+ ],
+ "analyse": [
+ "phpstan analyse src/"
+ ],
+ "phpmd": [
+ "bin/phpmd ./src/ text phpmd.xml"
+ ]
}
}
diff --git a/infection.json5 b/infection.json5
new file mode 100644
index 0000000..91f5a9c
--- /dev/null
+++ b/infection.json5
@@ -0,0 +1,14 @@
+{
+ "$schema": "vendor/infection/infection/resources/schema.json",
+ "source": {
+ "directories": [
+ "src"
+ ]
+ },
+ "logs": {
+ "text": "."
+ },
+ "mutators": {
+ "@default": true
+ }
+}
\ No newline at end of file
diff --git a/phpmd.xml b/phpmd.xml
new file mode 100644
index 0000000..5497422
--- /dev/null
+++ b/phpmd.xml
@@ -0,0 +1,21 @@
+
+
+
+ Phauthentic PHPMD rule set
+
+
+
+
+
+
+
+
+
+
+
diff --git a/phpstan.neon b/phpstan.neon
index 31f1e85..c308dcf 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -2,4 +2,3 @@ parameters:
level: 8
paths:
- src
- checkGenericClassInNonGenericObjectType: false
diff --git a/src/ErrorResponse.php b/src/ErrorResponse.php
index 97a01b1..0b18d6a 100644
--- a/src/ErrorResponse.php
+++ b/src/ErrorResponse.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use InvalidArgumentException;
diff --git a/src/ErrorResponseExceptionBasedFactoryInterface.php b/src/ErrorResponseExceptionBasedFactoryInterface.php
index b642cc2..6c52891 100644
--- a/src/ErrorResponseExceptionBasedFactoryInterface.php
+++ b/src/ErrorResponseExceptionBasedFactoryInterface.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use Exception;
diff --git a/src/ErrorResponseFactory.php b/src/ErrorResponseFactory.php
index 5583453..5692bad 100644
--- a/src/ErrorResponseFactory.php
+++ b/src/ErrorResponseFactory.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use Exception;
diff --git a/src/ErrorResponseFactoryInterface.php b/src/ErrorResponseFactoryInterface.php
index 3b49c51..fd46daf 100644
--- a/src/ErrorResponseFactoryInterface.php
+++ b/src/ErrorResponseFactoryInterface.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use Exception;
diff --git a/src/ErrorResponseInterface.php b/src/ErrorResponseInterface.php
index c0efd42..434af19 100644
--- a/src/ErrorResponseInterface.php
+++ b/src/ErrorResponseInterface.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
/**
* ErrorResponseInterface
diff --git a/src/ErrorResponseMiddleware.php b/src/ErrorResponseMiddleware.php
index 13d8d87..09777be 100644
--- a/src/ErrorResponseMiddleware.php
+++ b/src/ErrorResponseMiddleware.php
@@ -2,32 +2,51 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use Exception;
+use JsonException;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
+/**
+ *
+ */
class ErrorResponseMiddleware implements MiddlewareInterface
{
/**
* @param ResponseFactoryInterface $responseFactory
* @param ErrorResponseExceptionBasedFactoryInterface $errorResponseFactory
* @param array $exceptionClasses
- * @return void
+ * @param bool $onlyOnJsonRequests
*/
public function __construct(
protected ResponseFactoryInterface $responseFactory,
protected ErrorResponseExceptionBasedFactoryInterface $errorResponseFactory,
- protected array $exceptionClasses = [Exception::class]
+ protected array $exceptionClasses = [Exception::class],
+ protected bool $onlyOnJsonRequests = true
) {
}
- public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
- {
+ /**
+ * {@inheritDoc}
+ *
+ * @param ServerRequestInterface $request
+ * @param RequestHandlerInterface $handler
+ * @return ResponseInterface
+ * @throws Exception
+ */
+ public function process(
+ ServerRequestInterface $request,
+ RequestHandlerInterface $handler
+ ): ResponseInterface {
+ if (!$this->isJsonRequest($request)) {
+ return $handler->handle($request);
+ }
+
try {
return $handler->handle($request);
} catch (Exception $exception) {
@@ -41,6 +60,12 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
}
}
+ protected function isJsonRequest(ServerRequestInterface $request): bool
+ {
+ return $this->onlyOnJsonRequests
+ && in_array('application/json', $request->getHeader('Accept'), true);
+ }
+
protected function isAnInterceptableException(Exception $exception): bool
{
foreach ($this->exceptionClasses as $class) {
@@ -52,6 +77,11 @@ protected function isAnInterceptableException(Exception $exception): bool
return false;
}
+ /**
+ * @param ErrorResponseInterface $errorResponse
+ * @return string
+ * @throws JsonException
+ */
protected function errorResponseToJson(ErrorResponseInterface $errorResponse): string
{
return json_encode($errorResponse->toArray(), JSON_THROW_ON_ERROR);
@@ -60,6 +90,7 @@ protected function errorResponseToJson(ErrorResponseInterface $errorResponse): s
public function createResponse(ErrorResponseInterface $errorResponse): ResponseInterface
{
$response = $this->responseFactory->createResponse($errorResponse->getStatus());
+
$body = $response->getBody();
$body->write($this->errorResponseToJson($errorResponse));
diff --git a/src/MultiErrorCollectionResponseBuilder.php b/src/MultiErrorCollectionResponseBuilder.php
index 945092f..1088007 100644
--- a/src/MultiErrorCollectionResponseBuilder.php
+++ b/src/MultiErrorCollectionResponseBuilder.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse;
+namespace Phauthentic\ProblemDetails;
use InvalidArgumentException;
diff --git a/tests/CustomException.php b/tests/CustomException.php
index 8942dee..8573d74 100644
--- a/tests/CustomException.php
+++ b/tests/CustomException.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse\Tests;
+namespace Phauthentic\ProblemDetails\Tests;
use Exception;
diff --git a/tests/ErrorResponseFactoryTest.php b/tests/ErrorResponseFactoryTest.php
index 6f97a87..5d8a15f 100644
--- a/tests/ErrorResponseFactoryTest.php
+++ b/tests/ErrorResponseFactoryTest.php
@@ -2,12 +2,12 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse\Tests;
+namespace Phauthentic\ProblemDetails\Tests;
use Exception;
-use Phauthentic\ErrorResponse\ErrorResponse;
-use Phauthentic\ErrorResponse\ErrorResponseFactory;
-use Phauthentic\ErrorResponse\ErrorResponseInterface;
+use Phauthentic\ProblemDetails\ErrorResponse;
+use Phauthentic\ProblemDetails\ErrorResponseFactory;
+use Phauthentic\ProblemDetails\ErrorResponseInterface;
use PHPUnit\Framework\TestCase;
class ErrorResponseFactoryTest extends TestCase
diff --git a/tests/ErrorResponseMiddlewareTest.php b/tests/ErrorResponseMiddlewareTest.php
index c8058f3..44d04da 100644
--- a/tests/ErrorResponseMiddlewareTest.php
+++ b/tests/ErrorResponseMiddlewareTest.php
@@ -2,19 +2,19 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse\Tests;
+namespace Phauthentic\ProblemDetails\Tests;
use Exception;
use Nyholm\Psr7\Factory\Psr17Factory;
-use Phauthentic\ErrorResponse\ErrorResponseFactory;
-use Phauthentic\ErrorResponse\ErrorResponseMiddleware;
+use Phauthentic\ProblemDetails\ErrorResponseFactory;
+use Phauthentic\ProblemDetails\ErrorResponseMiddleware;
use PHPUnit\Framework\TestCase;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
class ErrorResponseMiddlewareTest extends TestCase
{
- public function testProcessErrorResponse(): void
+ public function testThatExceptionInHandlerWillReturnErrorResponse(): void
{
$middleware = new ErrorResponseMiddleware(
new Psr17Factory(),
@@ -38,6 +38,7 @@ public function testProcessErrorResponse(): void
(string)$response->getBody()
);
$this->assertSame(500, $response->getStatusCode());
+ $this->assertSame('application/problem+json', $response->getHeaderLine('Content-Type'));
}
public function testProcessHandlesUnhandledException(): void
diff --git a/tests/ErrorResponseTest.php b/tests/ErrorResponseTest.php
index 14501cc..1355a8a 100644
--- a/tests/ErrorResponseTest.php
+++ b/tests/ErrorResponseTest.php
@@ -2,10 +2,10 @@
declare(strict_types=1);
-namespace Phauthentic\ErrorResponse\Tests;
+namespace Phauthentic\ProblemDetails\Tests;
use InvalidArgumentException;
-use Phauthentic\ErrorResponse\ErrorResponse;
+use Phauthentic\ProblemDetails\ErrorResponse;
use PHPUnit\Framework\TestCase;
class ErrorResponseTest extends TestCase