Skip to content

Commit 244bdf1

Browse files
committed
Merge branch 'feature/change-formatter-interface'
2 parents ec80134 + b1c8c27 commit 244bdf1

17 files changed

+183
-197
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ php:
44
- 7.0
55
- 7.1
66
- 7.2
7+
- 7.3
78

89
before_script:
910
- composer install -n

CHANGELOG.md

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,120 +5,93 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8-
## [Unreleased]
9-
8+
## [2.0.0] - 2019-05-10
109
### Added
11-
1210
- Use `phpstan` as a dev dependency to detect bugs
1311

1412
### Changed
15-
1613
- Always catches exceptions
1714
- Create separate classes for error formatters
1815
- Allow any number of formatters to be used
1916
- Allow any exception to define HTTP status code
2017

21-
## [1.2.0] - 2018-08-04
18+
### Removed
19+
- Ability to handle responses with http error codes (400-599). A new package will be created for that. This package only handles exceptions.
20+
- `HttpErrorException` class (that was simply an extension of `Middlewares\Utils\HttpErrorException`). You can use `Middlewares\Utils\HttpErrorException` directly.
2221

22+
## [1.2.0] - 2018-08-04
2323
### Added
24-
2524
- PSR-17 support
2625
- Added a first argument to the constructor of `ErrorHandlerDefault` to customize the `ResponseFactoryInterface`
2726

2827
## [1.1.0] - 2018-06-25
29-
3028
### Changed
31-
3229
- Use `HttpErrorException` from utils package
3330

3431
## [1.0.0] - 2018-01-26
35-
3632
### Added
37-
3833
- Improved testing and added code coverage reporting
3934
- Added tests for PHP 7.2
4035

4136
### Changed
42-
4337
- Upgraded to the final version of PSR-15 `psr/http-server-middleware`
4438

4539
### Fixed
46-
4740
- Updated license year
4841

4942
## [0.9.0] - 2017-12-16
50-
5143
### Changed
52-
5344
- The request handler used to generate the response must implement `Interop\Http\Server\RequestHandlerInterface`. Removed support for callables.
5445

5546
### Removed
56-
5747
- Removed `arguments()` option.
5848

5949
## [0.8.0] - 2017-11-13
60-
6150
### Changed
62-
6351
- Replaced `http-interop/http-middleware` with `http-interop/http-server-middleware`.
6452

6553
### Removed
66-
6754
- Removed support for PHP 5.x.
6855

6956
## [0.7.0] - 2017-09-21
70-
7157
### Changed
72-
7358
- Append `.dist` suffix to phpcs.xml and phpunit.xml files
7459
- Changed the configuration of phpcs and php_cs
7560
- Upgraded phpunit to the latest version and improved its config file
7661
- Updated to `http-interop/http-middleware#0.5`
7762

7863
## [0.6.0] - 2017-03-26
79-
8064
### Changed
81-
8265
- Added `Middlewares\HttpErrorException` class to allow to pass data context to the error handler
8366
- Changed the error handler signature. The attribute `error` contains an instance of `Middlewares\HttpErrorException` instead an array.
8467
- Updated to `middlewares/utils#~0.11`
8568

8669
## [0.5.0] - 2017-02-05
87-
8870
### Changed
89-
9071
- Updated to `middlewares/utils#~0.9`
9172

9273
## [0.4.0] - 2016-12-26
93-
9474
### Changed
95-
9675
- Updated tests
9776
- Updated to `http-interop/http-middleware#0.4`
9877
- Updated `friendsofphp/php-cs-fixer#2.0`
9978

10079
## [0.3.0] - 2016-11-22
101-
10280
### Changed
103-
10481
- Updated to `http-interop/http-middleware#0.3`
10582

10683
## [0.2.0] - 2016-11-19
107-
10884
### Added
109-
11085
- New option `attribute()` to change the attribute name used to pass the error info to the handler.
11186

11287
### Changed
113-
11488
- Changed the handler signature to `function(ServerRequestInterface $request)`.
11589
- The error info is passed to the handler using an array stored in the request attribute `error`.
11690

11791
## 0.1.0 - 2016-10-03
118-
11992
First version
12093

121-
[Unreleased]: https://github.com/middlewares/error-handler/compare/v1.2.0...HEAD
94+
[2.0.0]: https://github.com/middlewares/error-handler/compare/v1.2.0...v2.0.0
12295
[1.2.0]: https://github.com/middlewares/error-handler/compare/v1.1.0...v1.2.0
12396
[1.1.0]: https://github.com/middlewares/error-handler/compare/v1.0.0...v1.1.0
12497
[1.0.0]: https://github.com/middlewares/error-handler/compare/v0.9.0...v1.0.0

README.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Middleware to catch and format errors encountered while handling the request.
1111

1212
## Requirements
1313

14-
* PHP >= 7.1
14+
* PHP >= 7.0
1515
* A [PSR-7 http library](https://github.com/middlewares/awesome-psr15-middlewares#psr-7-implementations)
1616
* A [PSR-15 middleware dispatcher](https://github.com/middlewares/awesome-psr15-middlewares#dispatcher)
1717

@@ -31,19 +31,19 @@ use Middlewares\ErrorHandler;
3131
use Middlewares\Utils\Dispatcher;
3232

3333
// Create a new ErrorHandler instance
34-
$errorHandler = new ErrorHandler();
35-
3634
// Any number of formatters can be added. One will be picked based on the Accept
3735
// header of the request. If no formatter matches, the PlainFormatter will be used.
38-
$errorHandler->addFormatters(
36+
$errorHandler = new ErrorHandler([
3937
new ErrorFormatter\GifFormatter(),
4038
new ErrorFormatter\HtmlFormatter(),
4139
new ErrorFormatter\JpegFormatter(),
4240
new ErrorFormatter\JsonFormatter(),
4341
new ErrorFormatter\PngFormatter(),
4442
new ErrorFormatter\SvgFormatter(),
4543
new ErrorFormatter\XmlFormatter(),
46-
);
44+
]);
45+
46+
$errorHandler->defaultFormatter(new ErrorFormatter\PlainFormatter());
4747

4848
// ErrorHandler should always be the first middleware in the stack!
4949
$dispatcher = new Dispatcher([
@@ -60,14 +60,13 @@ $response = $dispatcher->dispatch($request);
6060

6161
## Options
6262

63-
### `__construct(ResponseFactoryInterface $responseFactory = null, StreamFactoryInterface $streamFactory = null)`
64-
65-
Provide a specific response and stream factory. If not provided, will be detected based on available PSR-17 implementations.
63+
### `__construct(array $formatters [])`
6664

67-
### `addFormatters(FormatterInterface ...$formatters)`
65+
Add the [formatters](src/Formatter) to be used (instances of `Middlewares\ErrorFormatter\FormatterInterface`).
6866

69-
Add additional error [formatters](src/Formatter). Default is `PlainFormatter`.
67+
### `defaultFormatter(FormatterInterface $defaultFormatter)`
7068

69+
Set the default formatter if no content-type matches (by default is `PlainFormatter`).
7170
---
7271

7372
Please see [CHANGELOG](CHANGELOG.md) for more information about recent changes and [CONTRIBUTING](CONTRIBUTING.md) for contributing details.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
declare(strict_types = 1);
3+
4+
namespace Middlewares\ErrorFormatter;
5+
6+
use Middlewares\Utils\Factory;
7+
use Middlewares\Utils\HttpErrorException;
8+
use Psr\Http\Message\ResponseFactoryInterface;
9+
use Psr\Http\Message\StreamFactoryInterface;
10+
use Psr\Http\Message\ResponseInterface;
11+
use Psr\Http\Message\ServerRequestInterface;
12+
use Throwable;
13+
14+
abstract class AbstractFormatter implements FormatterInterface
15+
{
16+
/** @var ResponseFactoryInterface */
17+
protected $responseFactory;
18+
19+
/** @var StreamFactoryInterface */
20+
protected $streamFactory;
21+
22+
/** @var string[] */
23+
protected $contentTypes = [];
24+
25+
public function __construct(
26+
ResponseFactoryInterface $responseFactory = null,
27+
StreamFactoryInterface $streamFactory = null
28+
) {
29+
$this->responseFactory = $responseFactory ?? Factory::getResponseFactory();
30+
$this->streamFactory = $streamFactory ?? Factory::getStreamFactory();
31+
}
32+
33+
public function isValid(Throwable $error, ServerRequestInterface $request): bool
34+
{
35+
return $this->getContentType($request) ? true : false;
36+
}
37+
38+
abstract protected function format(Throwable $error): string;
39+
40+
public function handle(Throwable $error, ServerRequestInterface $request): ResponseInterface
41+
{
42+
$response = $this->responseFactory->createResponse($this->errorStatus($error));
43+
$body = $this->streamFactory->createStream($this->format($error));
44+
$response = $response->withBody($body);
45+
46+
$contentType = $this->getContentType($request);
47+
48+
return $response->withHeader('Content-Type', $contentType ? $contentType : $this->contentTypes[0]);
49+
}
50+
51+
protected function errorStatus(Throwable $error): int
52+
{
53+
if ($error instanceof HttpErrorException) {
54+
return $error->getCode();
55+
}
56+
57+
if (method_exists($error, 'getStatusCode')) {
58+
return $error->getStatusCode();
59+
}
60+
61+
return 500;
62+
}
63+
64+
/**
65+
* @return string|null
66+
*/
67+
protected function getContentType(ServerRequestInterface $request)
68+
{
69+
$accept = $request->getHeaderLine('Accept');
70+
71+
foreach ($this->contentTypes as $type) {
72+
if (stripos($accept, $type) !== false) {
73+
return $type;
74+
}
75+
}
76+
}
77+
}

src/ErrorFormatter/AbstractImageFormatter.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?php
2-
declare(strict_types=1);
2+
declare(strict_types = 1);
33

44
namespace Middlewares\ErrorFormatter;
55

66
use Throwable;
77

8-
abstract class AbstractImageFormatter implements FormatterInterface
8+
abstract class AbstractImageFormatter extends AbstractFormatter
99
{
1010
/**
1111
* Create an image resource from an error
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
<?php
2-
declare(strict_types=1);
2+
declare(strict_types = 1);
33

44
namespace Middlewares\ErrorFormatter;
55

6+
use Psr\Http\Message\ResponseInterface;
7+
use Psr\Http\Message\ServerRequestInterface;
68
use Throwable;
79

810
interface FormatterInterface
911
{
1012
/**
11-
* Get supported content types
12-
*
13-
* @return string[]
13+
* Check whether the error can be handled by this formatter
1414
*/
15-
public function contentTypes(): array;
15+
public function isValid(Throwable $error, ServerRequestInterface $request): bool;
1616

1717
/**
18-
* Format an error as a string
18+
* Create a response with this error
1919
*/
20-
public function format(Throwable $error): string;
20+
public function handle(Throwable $error, ServerRequestInterface $request): ResponseInterface;
2121
}
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
<?php
2-
declare(strict_types=1);
2+
declare(strict_types = 1);
33

44
namespace Middlewares\ErrorFormatter;
55

66
use Throwable;
77

88
class GifFormatter extends AbstractImageFormatter
99
{
10-
public function contentTypes(): array
11-
{
12-
return [
13-
'image/gif',
14-
];
15-
}
10+
protected $contentTypes = [
11+
'image/gif',
12+
];
1613

17-
public function format(Throwable $error): string
14+
protected function format(Throwable $error): string
1815
{
1916
ob_start();
2017
imagegif($this->createImage($error));
21-
return ob_get_clean();
18+
return (string) ob_get_clean();
2219
}
2320
}

src/ErrorFormatter/HtmlFormatter.php

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
<?php
2-
declare(strict_types=1);
2+
declare(strict_types = 1);
33

44
namespace Middlewares\ErrorFormatter;
55

66
use Throwable;
77

8-
class HtmlFormatter implements FormatterInterface
8+
class HtmlFormatter extends AbstractFormatter
99
{
10-
public function contentTypes(): array
11-
{
12-
return [
13-
'text/html',
14-
];
15-
}
10+
protected $contentTypes = [
11+
'text/html',
12+
];
1613

17-
public function format(Throwable $error): string
14+
protected function format(Throwable $error): string
1815
{
1916
$type = get_class($error);
2017
$code = $error->getCode();
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,20 @@
11
<?php
2-
declare(strict_types=1);
2+
declare(strict_types = 1);
33

44
namespace Middlewares\ErrorFormatter;
55

66
use Throwable;
77

88
class JpegFormatter extends AbstractImageFormatter
99
{
10-
public function contentTypes(): array
11-
{
12-
return [
13-
'image/jpeg',
14-
];
15-
}
10+
protected $contentTypes = [
11+
'image/jpeg',
12+
];
1613

17-
public function format(Throwable $error): string
14+
protected function format(Throwable $error): string
1815
{
1916
ob_start();
2017
imagejpeg($this->createImage($error));
21-
return ob_get_clean();
18+
return (string) ob_get_clean();
2219
}
2320
}

0 commit comments

Comments
 (0)