Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add debug stuff to application's fallback handler #145

Merged
merged 12 commits into from
Jun 21, 2024
1 change: 1 addition & 0 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"Yiisoft\\Assets\\AssetManager",
"Yiisoft\\Assets\\AssetPublisherInterface",
"Yiisoft\\Yii\\View\\ViewRenderer",
"Yiisoft\\Yii\\Http\\Application",
"Codeception\\Event\\FailEvent",
"Codeception\\Event\\PrintResultEvent",
"Codeception\\Event\\TestEvent",
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"yiisoft/di": "^1.0",
"yiisoft/friendly-exception": "^1.1",
"yiisoft/http": "^1.2",
"yiisoft/middleware-dispatcher": "^5.2",
"yiisoft/router": "^3.0",
"yiisoft/translator": "^3.0",
"yiisoft/var-dumper": "^1.4",
Expand Down
12 changes: 12 additions & 0 deletions config/di-web.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use Cycle\Database\DatabaseProviderInterface;
use Psr\Container\ContainerInterface;
use Yiisoft\Db\Connection\ConnectionInterface;
use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper;
use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper;
use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepository;
use Yiisoft\Yii\Debug\Api\Debug\Repository\CollectorRepositoryInterface;
use Yiisoft\Yii\Debug\Api\Inspector\Database\Cycle\CycleSchemaProvider;
Expand Down Expand Up @@ -34,4 +36,14 @@
)
);
},
HttpApplicationWrapper::class => [
'__construct()' => [
'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'],
],
],
RouteCollectorWrapper::class => [
'__construct()' => [
'middlewareDefinitions' => $params['yiisoft/yii-debug-api']['middlewares'],
],
],
];
4 changes: 4 additions & 0 deletions config/params.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
declare(strict_types=1);

use Codeception\Extension;
use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders;
use Yiisoft\Yii\Debug\Api\Inspector\Command\CodeceptionCommand;
use Yiisoft\Yii\Debug\Api\Inspector\Command\PHPUnitCommand;
use Yiisoft\Yii\Debug\Api\Inspector\Command\PsalmCommand;
Expand All @@ -26,6 +27,9 @@
'enabled' => true,
'allowedIPs' => ['127.0.0.1', '::1'],
'allowedHosts' => [],
'middlewares' => [
DebugHeaders::class,
],
'inspector' => [
'commandMap' => [
'tests' => $testCommands,
Expand Down
37 changes: 37 additions & 0 deletions src/Debug/Http/HttpApplicationWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Http;

use Closure;
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
use Yiisoft\Yii\Debug\Api\Debug\Middleware\MiddlewareDispatcherMiddleware;
use Yiisoft\Yii\Http\Application;

final readonly class HttpApplicationWrapper
{
public function __construct(
private MiddlewareDispatcher $middlewareDispatcher,
private array $middlewareDefinitions,
) {
}

public function wrap(Application $application): void

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 20 in src/Debug/Http/HttpApplicationWrapper.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Http/HttpApplicationWrapper.php:20:26: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)
{
$middlewareDispatcher = $this->middlewareDispatcher;
$middlewareDefinitions = $this->middlewareDefinitions;

$closure = Closure::bind(static function (Application $application) use (
$middlewareDispatcher,
$middlewareDefinitions,
) {
$application->dispatcher = $middlewareDispatcher->withMiddlewares([
...$middlewareDefinitions,
['class' => MiddlewareDispatcherMiddleware::class, '$middlewareDispatcher' => $application->dispatcher],
]);;
}, null, $application);

$closure($application);
}
}
20 changes: 20 additions & 0 deletions src/Debug/Http/RouteCollectorWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Http;

use Yiisoft\Router\RouteCollectorInterface;

final class RouteCollectorWrapper
{
public function __construct(
private array $middlewareDefinitions,
) {
}

public function wrap(RouteCollectorInterface $routeCollector): void
{
$routeCollector->prependMiddleware(...$this->middlewareDefinitions);
}
}
24 changes: 24 additions & 0 deletions src/Debug/Middleware/MiddlewareDispatcherMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Debug\Api\Debug\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;

final class MiddlewareDispatcherMiddleware implements MiddlewareInterface
{
public function __construct(
public MiddlewareDispatcher $middlewareDispatcher
) {
}

public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
return $this->middlewareDispatcher->dispatch($request, $handler);
}
}
22 changes: 19 additions & 3 deletions src/Debug/Provider/DebugApiProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Psr\Container\ContainerInterface;
use Yiisoft\Di\ServiceProviderInterface;
use Yiisoft\Router\RouteCollectorInterface;
use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders;
use Yiisoft\Yii\Debug\Api\Debug\Http\HttpApplicationWrapper;
use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper;
use Yiisoft\Yii\Http\Application;

final class DebugApiProvider implements ServiceProviderInterface
{
Expand All @@ -22,10 +24,24 @@
public function getExtensions(): array
{
return [
RouteCollectorInterface::class => static function (ContainerInterface $container, RouteCollectorInterface $routeCollector) {
$routeCollector->prependMiddleware(DebugHeaders::class);
RouteCollectorInterface::class => static function (
ContainerInterface $container,
RouteCollectorInterface $routeCollector
) {
/**
* Register debug middlewares twice because a `Subfolder` middleware may rewrite base URL
*/
$routerCollectionWrapper = $container->get(RouteCollectorWrapper::class);
$routerCollectionWrapper->wrap($routeCollector);

return $routeCollector;
},
Application::class => static function (ContainerInterface $container, Application $application) {

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.1-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.2-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:13: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)

Check failure on line 39 in src/Debug/Provider/DebugApiProvider.php

View workflow job for this annotation

GitHub Actions / psalm / PHP 8.3-ubuntu-latest

UndefinedClass

src/Debug/Provider/DebugApiProvider.php:39:83: UndefinedClass: Class, interface or enum named Yiisoft\Yii\Http\Application does not exist (see https://psalm.dev/019)
$applicationWrapper = $container->get(HttpApplicationWrapper::class);
$applicationWrapper->wrap($application);

return $application;
},
];
}
}
14 changes: 12 additions & 2 deletions tests/Unit/Debug/Provider/DebugApiProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
namespace Yiisoft\Yii\Debug\Api\Tests\Unit\Debug\Provider;

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Yiisoft\Router\RouteCollectorInterface;
use Yiisoft\Yii\Debug\Api\Debug\Http\RouteCollectorWrapper;
use Yiisoft\Yii\Debug\Api\Debug\Middleware\DebugHeaders;
use Yiisoft\Yii\Debug\Api\Debug\Provider\DebugApiProvider;

Expand All @@ -25,12 +27,20 @@ public function testExtension(): void
$routeCollectorDecorator = $extensions[RouteCollectorInterface::class];
$this->assertIsCallable($routeCollectorDecorator);

$middlewares = [DebugHeaders::class];

$container = $this->createMock(ContainerInterface::class);
$container->expects($this->once())
->method('get')
->with(RouteCollectorWrapper::class)
->willReturn(new RouteCollectorWrapper($middlewares));

$routeCollector = $this->createMock(RouteCollectorInterface::class);
$routeCollector->expects($this->once())
->method('prependMiddleware')
->with(DebugHeaders::class)
->with(...$middlewares)
->willReturn($routeCollector);

$this->assertSame($routeCollector, $routeCollectorDecorator($routeCollector));
$this->assertSame($routeCollector, $routeCollectorDecorator($container, $routeCollector));
}
}
Loading