Skip to content

Commit daa1985

Browse files
authored
psr-17 support (#27)
* Add psr-17 support, require psr-11 container in factories, change config service key * php 7.3 not existig in travis yet :) * Readme improvements
1 parent 160e792 commit daa1985

13 files changed

+171
-103
lines changed

README.md

+39-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
# phpdebugbar middleware [![Build Status](https://travis-ci.org/php-middleware/phpdebugbar.svg?branch=master)](https://travis-ci.org/php-middleware/phpdebugbar)
2-
PHP Debug bar [PSR-15](https://www.php-fig.org/psr/psr-15/) middleware with [PSR-7](https://www.php-fig.org/psr/psr-7/). Also supports [PSR-11](https://www.php-fig.org/psr/psr-11/)
2+
[PHP Debug Bar](http://phpdebugbar.com/) as framework-agnostic [PSR-15 middleware](https://www.php-fig.org/psr/psr-15/) with [PSR-7 messages](https://www.php-fig.org/psr/psr-7/) created by [PSR-17 message factories](https://www.php-fig.org/psr/psr-17/). Also provides [PSR-11 container invokable factories](https://www.php-fig.org/psr/psr-11/).
33

4-
This middleware provide framework-agnostic possibility to attach [PHP Debug Bar](http://phpdebugbar.com/) to your response (html on non-html!).
4+
Framework-agnostic way to attach [PHP Debug Bar](http://phpdebugbar.com/) to your response (html or non-html!).
55

66
## Installation
77

88
```
9-
composer require php-middleware/php-debug-bar
9+
composer require --dev php-middleware/php-debug-bar
1010
```
1111

12-
To build this middleware you need to injecting inside `PhpDebugBarMiddleware` instance `DebugBar\JavascriptRenderer` (you can get it from `DebugBar\StandardDebugBar`) and add middleware to your middleware runner. Or use default factory.
12+
To build middleware you need to inject `DebugBar\JavascriptRenderer` (you can get it from `DebugBar\StandardDebugBar`) inside `PhpDebugBarMiddleware` and add it into your middleware runner:
1313

1414
```php
1515
$debugbar = new DebugBar\StandardDebugBar();
1616
$debugbarRenderer = $debugbar->getJavascriptRenderer('/phpdebugbar');
17-
$middleware = new PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware($debugbarRenderer);
18-
19-
// OR
17+
$middleware = new PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware($debugbarRenderer, $psr17ResponseFactory, $psr17StreamFactory);
2018

19+
// or use provided factory
2120
$factory = new PhpMiddleware\PhpDebugBar\PhpDebugBarMiddlewareFactory();
22-
$middleware = $factory();
21+
$middleware = $factory($psr11Container);
2322

2423
$app = new MiddlewareRunner();
2524
$app->add($middleware);
@@ -30,40 +29,57 @@ You don't need to copy any static assets from phpdebugbar vendor!
3029

3130
### How to force disable or enable PHP Debug Bar?
3231

33-
Sometimes you want to have control when enable (or not) PHP Debug Bar:
32+
Sometimes you want to have control when enable or disable PHP Debug Bar:
3433
* custom content negotiation,
3534
* allow to debug redirects responses.
3635

3736
We allow you to disable attaching phpdebugbar using `X-Enable-Debug-Bar: false` header, cookie or request attribute.
3837
To force enable just send request with `X-Enable-Debug-Bar` header, cookie or request attribute with `true` value.
3938

39+
### PSR-17
40+
41+
This package isn't require any PSR-7 implementation - you need to provide it by own. Middleware require ResponseFactory and StreamFactory interfaces. [List of existing interfaces](https://packagist.org/providers/psr/http-factory-implementation).
42+
43+
#### ... and PSR-11
44+
45+
If you use provided PSR-11 factories, then you container must have services registered as PSR-17 interface's name. Example for [zend-diactoros](https://github.com/zendframework/zend-diactoros) implementation and [Pimple](https://pimple.symfony.com/):
46+
47+
```php
48+
$container[Psr\Http\Message\ResponseInterface::class] = new Zend\Diactoros\ResponseFactory();
49+
$container[Psr\Http\Message\StreamFactoryInterface] = new Zend\Diactoros\StreamFactory();
50+
```
51+
4052
### How to install on Zend Expressive?
4153

42-
You need to register ConfigProvider and pipe provided middleware:
54+
You need to register `PhpMiddleware\PhpDebugBar\ConfigProvider` and pipe provided middleware:
4355

4456
```php
45-
$app->pipe(PhpDebugBarMiddleware::class);
57+
$app->pipe(\PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware::class);
4658
```
4759

48-
For more follow Zend Expressive [documentation](https://docs.zendframework.com/zend-expressive/v3/features/modular-applications/).
60+
For more - follow Zend Expressive [documentation](https://docs.zendframework.com/zend-expressive/v3/features/modular-applications/).
4961

5062
### How to install on Slim 3?
5163

52-
Add existing factory to container:
64+
Register factories in container:
5365

5466
```php
55-
$container['debugbar_middleware'] = new PhpMiddleware\PhpDebugBar\PhpDebugBarMiddlewareFactory();
67+
foreach (ConfigProvider::getConfig()['dependencies']['factories'] as $key => $factory) {
68+
$container[$key] = new $factory();
69+
}
5670
```
5771

5872
and add middleware from container to app:
5973

6074
```php
61-
$app->add($app->getContainer()->get('debugbar_middleware'));
75+
$app->add(
76+
$app->getContainer()->get(\PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware::class)
77+
);
6278
```
6379

6480
### How to configure using existing factories?
6581

66-
Put array with configuration into `config` service in your container:
82+
Put array with configuration into `PhpMiddleware\PhpDebugBar\ConfigProvider` service in your container:
6783

6884
```php
6985
return [
@@ -81,10 +97,16 @@ return [
8197
];
8298
```
8399

100+
You can override existing configuration by merge default configuration with your own (example):
101+
102+
```php
103+
return array_merge(PhpMiddleware\PhpDebugBar\ConfigProvider::getConfig(), $myOverritenConfig);
104+
```
105+
84106
## It's just works with any modern php framework!
85107

86108
Middleware tested on:
87109
* [Zend Expressive](https://github.com/zendframework/zend-expressive)
88110
* [Slim 3.x](https://github.com/slimphp/Slim)
89111

90-
And any other modern framework [supported middlewares and PSR-7](https://mwop.net/blog/2015-01-08-on-http-middleware-and-psr-7.html).
112+
And any other modern framework [supported PSR-17 middlewares and PSR-7](https://mwop.net/blog/2015-01-08-on-http-middleware-and-psr-7.html).

composer.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,17 @@
1818
"psr/http-server-middleware": "^1.0",
1919
"psr/container": "^1.0",
2020
"psr/http-message": "^1.0.1",
21-
"zendframework/zend-diactoros": "^1.1.3 || ^2.0"
21+
"psr/http-factory": "^1.0",
22+
"psr/http-factory-implementation": "^1.0"
2223
},
2324
"require-dev": {
2425
"phpunit/phpunit": "^7.1.2",
2526
"mikey179/vfsStream": "^1.6.4",
2627
"slim/slim": "^3.0",
2728
"zendframework/zend-expressive": "^3.0",
2829
"zendframework/zend-expressive-fastroute": "^3.0.1",
29-
"zendframework/zend-servicemanager": "^3.3.2"
30+
"zendframework/zend-servicemanager": "^3.3.2",
31+
"zendframework/zend-diactoros": "^2.0"
3032
},
3133
"autoload": {
3234
"psr-4": {

config/dependency.config.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
return [
44
'factories' => [
5-
PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware::class => PhpMiddleware\PhpDebugBar\PhpDebugBarMiddlewareFactory::class,
6-
DebugBar\DataCollector\ConfigCollector::class => PhpMiddleware\PhpDebugBar\ConfigCollectorFactory::class,
5+
\PhpMiddleware\PhpDebugBar\PhpDebugBarMiddleware::class => \PhpMiddleware\PhpDebugBar\PhpDebugBarMiddlewareFactory::class,
6+
\DebugBar\DataCollector\ConfigCollector::class => \PhpMiddleware\PhpDebugBar\ConfigCollectorFactory::class,
7+
\PhpMiddleware\PhpDebugBar\ConfigProvider::class => \PhpMiddleware\PhpDebugBar\ConfigProvider::class,
8+
\DebugBar\DebugBar::class => \PhpMiddleware\PhpDebugBar\StandardDebugBarFactory::class,
9+
\DebugBar\JavascriptRenderer::class => \PhpMiddleware\PhpDebugBar\JavascriptRendererFactory::class,
710
],
811
];

phpunit.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<phpunit bootstrap="./vendor/autoload.php" colors="true">
44
<testsuites>
5-
<testsuite>
5+
<testsuite name="unit">
66
<directory>./test</directory>
77
</testsuite>
88
</testsuites>

src/ConfigCollectorFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ final class ConfigCollectorFactory
1010
{
1111
public function __invoke(ContainerInterface $container): ConfigCollector
1212
{
13-
$data = $container->get('config');
13+
$data = $container->get(ConfigProvider::class);
1414

1515
return new ConfigCollector($data, 'Config');
1616
}

src/JavascriptRendererFactory.php

+4-17
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,13 @@
99

1010
final class JavascriptRendererFactory
1111
{
12-
public function __invoke(ContainerInterface $container = null): JavascriptRenderer
12+
public function __invoke(ContainerInterface $container): JavascriptRenderer
1313
{
14-
if ($container === null || !$container->has(DebugBar::class)) {
15-
$debugbar = (new StandardDebugBarFactory())($container);
16-
} else {
17-
$debugbar = $container->get(DebugBar::class);
18-
}
14+
$debugbar = $container->get(DebugBar::class);
15+
$config = $container->get(ConfigProvider::class);
16+
$rendererOptions = $config['phpmiddleware']['phpdebugbar']['javascript_renderer'];
1917

2018
$renderer = new JavascriptRenderer($debugbar);
21-
22-
$config = $container !== null && $container->has('config') ? $container->get('config') : [];
23-
24-
if (isset($config['phpmiddleware']['phpdebugbar']['javascript_renderer'])) {
25-
$rendererOptions = $config['phpmiddleware']['phpdebugbar']['javascript_renderer'];
26-
} else {
27-
$rendererOptions = [
28-
'base_url' => '/phpdebugbar',
29-
];
30-
}
31-
3219
$renderer->setOptions($rendererOptions);
3320

3421
return $renderer;

src/PhpDebugBarMiddleware.php

+66-16
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,34 @@
55

66
use DebugBar\JavascriptRenderer as DebugBarRenderer;
77
use Psr\Http\Message\MessageInterface;
8+
use Psr\Http\Message\ResponseFactoryInterface;
89
use Psr\Http\Message\ResponseInterface as Response;
910
use Psr\Http\Message\ServerRequestInterface as ServerRequest;
11+
use Psr\Http\Message\StreamFactoryInterface;
1012
use Psr\Http\Message\UriInterface;
1113
use Psr\Http\Server\MiddlewareInterface;
1214
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
1315
use Slim\Http\Uri as SlimUri;
14-
use Zend\Diactoros\Response as DiactorosResponse;
15-
use Zend\Diactoros\Response\HtmlResponse;
16-
use Zend\Diactoros\Response\Serializer;
17-
use Zend\Diactoros\Stream;
1816

1917
/**
20-
* PhpDebugBarMiddleware
21-
*
2218
* @author Witold Wasiczko <[email protected]>
2319
*/
2420
final class PhpDebugBarMiddleware implements MiddlewareInterface
2521
{
2622
public const FORCE_KEY = 'X-Enable-Debug-Bar';
2723

28-
protected $debugBarRenderer;
24+
private $debugBarRenderer;
25+
private $responseFactory;
26+
private $streamFactory;
2927

30-
public function __construct(DebugBarRenderer $debugbarRenderer)
31-
{
28+
public function __construct(
29+
DebugBarRenderer $debugbarRenderer,
30+
ResponseFactoryInterface $responseFactory,
31+
StreamFactoryInterface $streamFactory
32+
) {
3233
$this->debugBarRenderer = $debugbarRenderer;
34+
$this->responseFactory = $responseFactory;
35+
$this->streamFactory = $streamFactory;
3336
}
3437

3538
/**
@@ -79,16 +82,20 @@ public function handle(ServerRequest $request): Response
7982
return $this->process($request, $handler);
8083
}
8184

82-
private function prepareHtmlResponseWithDebugBar(Response $response): HtmlResponse
85+
private function prepareHtmlResponseWithDebugBar(Response $response): Response
8386
{
8487
$head = $this->debugBarRenderer->renderHead();
8588
$body = $this->debugBarRenderer->render();
86-
$outResponseBody = Serializer::toString($response);
89+
$outResponseBody = $this->serializeResponse($response);
8790
$template = '<html><head>%s</head><body><h1>DebugBar</h1><p>Response:</p><pre>%s</pre>%s</body></html>';
8891
$escapedOutResponseBody = htmlspecialchars($outResponseBody);
8992
$result = sprintf($template, $head, $escapedOutResponseBody, $body);
9093

91-
return new HtmlResponse($result);
94+
$stream = $this->streamFactory->createStream($result);
95+
96+
return $this->responseFactory->createResponse(200)
97+
->withBody($stream)
98+
->withAddedHeader('Content-type', 'text/html');
9299
}
93100

94101
private function attachDebugBarToResponse(Response $response): Response
@@ -122,11 +129,11 @@ private function getStaticFile(UriInterface $uri): ?Response
122129
}
123130

124131
$contentType = $this->getContentTypeByFileName($fullPathToFile);
125-
$stream = new Stream($fullPathToFile, 'r');
132+
$stream = $this->streamFactory->createStreamFromResource(fopen($fullPathToFile, 'r'));
126133

127-
return new DiactorosResponse($stream, 200, [
128-
'Content-type' => $contentType,
129-
]);
134+
return $this->responseFactory->createResponse(200)
135+
->withBody($stream)
136+
->withAddedHeader('Content-type', $contentType);
130137
}
131138

132139
private function extractPath(UriInterface $uri): string
@@ -180,4 +187,47 @@ private function isRedirect(Response $response): bool
180187

181188
return ($statusCode >= 300 || $statusCode < 400) && $response->getHeaderLine('Location') !== '';
182189
}
190+
191+
private function serializeResponse(Response $response) : string
192+
{
193+
$reasonPhrase = $response->getReasonPhrase();
194+
$headers = $this->serializeHeaders($response->getHeaders());
195+
$body = (string) $response->getBody();
196+
$format = 'HTTP/%s %d%s%s%s';
197+
198+
if (! empty($headers)) {
199+
$headers = "\r\n" . $headers;
200+
}
201+
202+
$headers .= "\r\n\r\n";
203+
204+
return sprintf(
205+
$format,
206+
$response->getProtocolVersion(),
207+
$response->getStatusCode(),
208+
($reasonPhrase ? ' ' . $reasonPhrase : ''),
209+
$headers,
210+
$body
211+
);
212+
}
213+
214+
private function serializeHeaders(array $headers) : string
215+
{
216+
$lines = [];
217+
foreach ($headers as $header => $values) {
218+
$normalized = $this->filterHeader($header);
219+
foreach ($values as $value) {
220+
$lines[] = sprintf('%s: %s', $normalized, $value);
221+
}
222+
}
223+
224+
return implode("\r\n", $lines);
225+
}
226+
227+
private function filterHeader(string $header) : string
228+
{
229+
$filtered = str_replace('-', ' ', $header);
230+
$filtered = ucwords($filtered);
231+
return str_replace(' ', '-', $filtered);
232+
}
183233
}

src/PhpDebugBarMiddlewareFactory.php

+8-7
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55

66
use DebugBar\JavascriptRenderer;
77
use Psr\Container\ContainerInterface;
8+
use Psr\Http\Message\ResponseFactoryInterface;
9+
use Psr\Http\Message\StreamFactoryInterface;
810

911
final class PhpDebugBarMiddlewareFactory
1012
{
11-
public function __invoke(ContainerInterface $container = null): PhpDebugBarMiddleware
13+
public function __invoke(ContainerInterface $container): PhpDebugBarMiddleware
1214
{
13-
if ($container === null || !$container->has(JavascriptRenderer::class)) {
14-
$renderer = (new JavascriptRendererFactory())($container);
15-
} else {
16-
$renderer = $container->get(JavascriptRenderer::class);
17-
}
18-
return new PhpDebugBarMiddleware($renderer);
15+
$renderer = $container->get(JavascriptRenderer::class);
16+
$responseFactory = $container->get(ResponseFactoryInterface::class);
17+
$streamFactory = $container->get(StreamFactoryInterface::class);
18+
19+
return new PhpDebugBarMiddleware($renderer, $responseFactory, $streamFactory);
1920
}
2021
}

src/StandardDebugBarFactory.php

+13-12
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,25 @@
88

99
final class StandardDebugBarFactory
1010
{
11-
public function __invoke(ContainerInterface $container = null): StandardDebugBar
11+
public function __invoke(ContainerInterface $container): StandardDebugBar
1212
{
1313
$debugBar = new StandardDebugBar();
1414

15-
if ($container !== null) {
16-
$config = $container->has('config') ? $container->get('config') : [];
15+
$config = $container->get(ConfigProvider::class);
1716

18-
$collectors = $config['phpmiddleware']['phpdebugbar']['collectors'] ?: [];
17+
$collectors = $config['phpmiddleware']['phpdebugbar']['collectors'];
1918

20-
foreach ($collectors as $collectorName) {
21-
$collector = $container->get($collectorName);
22-
$debugBar->addCollector($collector);
23-
}
19+
foreach ($collectors as $collectorName) {
20+
$collector = $container->get($collectorName);
21+
$debugBar->addCollector($collector);
22+
}
23+
24+
$storage = $config['phpmiddleware']['phpdebugbar']['storage'];
2425

25-
if (isset($config['phpmiddleware']['phpdebugbar']['storage']) && is_string($config['phpmiddleware']['phpdebugbar']['storage'])) {
26-
$storage = $container->get($config['phpmiddleware']['phpdebugbar']['storage']);
27-
$debugBar->setStorage($config['phpmiddleware']['phpdebugbar']['storage']);
28-
}
26+
if (is_string($storage)) {
27+
$debugBar->setStorage(
28+
$container->get($storage)
29+
);
2930
}
3031

3132
return $debugBar;

0 commit comments

Comments
 (0)