Skip to content

Commit

Permalink
Add InvalidMiddlewareDefinitionException, improve tests, update dev d…
Browse files Browse the repository at this point in the history
…ependencies
  • Loading branch information
vjik committed Jan 20, 2021
1 parent 39b0bd9 commit 3591c4c
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 14 deletions.
6 changes: 3 additions & 3 deletions composer.json
Expand Up @@ -27,10 +27,10 @@
},
"require-dev": {
"nyholm/psr7": "^1.3",
"phpunit/phpunit": "^9.4",
"roave/infection-static-analysis-plugin": "^1.5",
"phpunit/phpunit": "^9.5",
"roave/infection-static-analysis-plugin": "^1.6",
"spatie/phpunit-watcher": "^1.23",
"vimeo/psalm": "^4.2"
"vimeo/psalm": "^4.3"
},
"autoload": {
"psr-4": {
Expand Down
58 changes: 58 additions & 0 deletions src/InvalidMiddlewareDefinitionException.php
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Middleware\Dispatcher;

use InvalidArgumentException;
use function get_class;
use function is_array;
use function is_object;
use function is_string;

final class InvalidMiddlewareDefinitionException extends InvalidArgumentException
{
/**
* @param array|callable|string $middlewareDefinition
*/
public function __construct($middlewareDefinition)
{
$message = 'Parameter should be either PSR middleware class name or a callable.';

$definitionString = $this->convertDefinitionToString($middlewareDefinition);
if ($definitionString !== null) {
$message .= ' Got ' . $definitionString . '.';
}

parent::__construct($message);
}

private function convertDefinitionToString($middlewareDefinition): ?string
{
if (is_object($middlewareDefinition)) {
return 'an instance of "' . get_class($middlewareDefinition) . '"';
}

if (is_string($middlewareDefinition)) {
return '"' . $middlewareDefinition . '"';
}

if (is_array($middlewareDefinition)) {
$items = $middlewareDefinition;
foreach ($middlewareDefinition as $key => $item) {
if (!is_string($item)) {
return null;
}
}
array_walk($items, static function (&$item, $key) {
$item = '"' . $item . '"';
if (is_string($key)) {
$item = '"' . $key . '" => ' . $item;
}
});
return '[' . implode(', ', $items) . ']';
}

return null;
}
}
5 changes: 3 additions & 2 deletions src/MiddlewareFactory.php
Expand Up @@ -4,7 +4,6 @@

namespace Yiisoft\Middleware\Dispatcher;

use InvalidArgumentException;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
Expand Down Expand Up @@ -96,6 +95,8 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
* are automatically injected using dependency injection container passed to the route.
* Current request and handler could be obtained by type-hinting for {@see ServerRequestInterface}
* and {@see RequestHandlerInterface}.
*
* @throws InvalidMiddlewareDefinitionException
*/
private function validateMiddleware($middlewareDefinition): void
{
Expand All @@ -107,7 +108,7 @@ private function validateMiddleware($middlewareDefinition): void
return;
}

throw new InvalidArgumentException('Parameter should be either PSR middleware class name or a callable.');
throw new InvalidMiddlewareDefinitionException($middlewareDefinition);
}

private function isCallable($definition): bool
Expand Down
46 changes: 46 additions & 0 deletions tests/InvalidMiddlewareDefinitionExceptionTest.php
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Middleware\Dispatcher\Tests;

use PHPUnit\Framework\TestCase;
use Yiisoft\Middleware\Dispatcher\InvalidMiddlewareDefinitionException;
use Yiisoft\Middleware\Dispatcher\Tests\Support\TestController;

final class InvalidMiddlewareDefinitionExceptionTest extends TestCase
{
public function dataBase(): array
{
return [
[
'test',
'"test"',
],
[
new TestController(),
'an instance of "Yiisoft\Middleware\Dispatcher\Tests\Support\TestController"',
],
[
[TestController::class, 'notExistsAction'],
'["Yiisoft\Middleware\Dispatcher\Tests\Support\TestController", "notExistsAction"]',
],
[
['class' => TestController::class, 'index'],
'["class" => "Yiisoft\Middleware\Dispatcher\Tests\Support\TestController", "index"]',
],
];
}

/**
* @dataProvider dataBase
*
* @param mixed $definition
* @param string $expected
*/
public function testBase($definition, string $expected): void
{
$exception = new InvalidMiddlewareDefinitionException($definition);
$this->assertStringEndsWith('. Got ' . $expected . '.', $exception->getMessage());
}
}
2 changes: 1 addition & 1 deletion tests/MiddlewareDispatcherTest.php
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Yiisoft\Router\Tests;
namespace Yiisoft\Middleware\Dispatcher\Tests;

use Nyholm\Psr7\Response;
use Nyholm\Psr7\ServerRequest;
Expand Down
20 changes: 12 additions & 8 deletions tests/MiddlewareFactoryTest.php
Expand Up @@ -2,9 +2,13 @@

declare(strict_types=1);

namespace Yiisoft\Middleware\Dispatcher\Tests;

use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Psr\Http\Server\MiddlewareInterface;
use stdClass;
use Yiisoft\Middleware\Dispatcher\InvalidMiddlewareDefinitionException;
use Yiisoft\Middleware\Dispatcher\MiddlewareFactory;
use Yiisoft\Middleware\Dispatcher\MiddlewareFactoryInterface;
use Yiisoft\Middleware\Dispatcher\Tests\Support\Container;
Expand All @@ -29,39 +33,39 @@ public function testCreateFromArray(): void

public function testInvalidMiddleware(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->getMiddlewareFactory()->create(new \stdClass());
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->getMiddlewareFactory()->create(new stdClass());
}

public function testInvalidMiddlewareAddWrongString(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->getMiddlewareFactory()->create('test');
}

public function testInvalidMiddlewareAddWrongStringClass(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->expectExceptionMessage('Parameter should be either PSR middleware class name or a callable.');
$this->getMiddlewareFactory()->create(TestController::class);
}

public function testInvalidMiddlewareAddWrongArraySize(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->getMiddlewareFactory()->create(['test']);
}

public function testInvalidMiddlewareAddWrongArrayClass(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->getMiddlewareFactory()->create(['class', 'test']);
}

public function testInvalidMiddlewareAddWrongArrayType(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->getMiddlewareFactory()->create(['class' => \Yiisoft\Router\Tests\Support\TestController::class, 'index']);
$this->expectException(InvalidMiddlewareDefinitionException::class);
$this->getMiddlewareFactory()->create(['class' => TestController::class, 'index']);
}

private function getMiddlewareFactory(ContainerInterface $container = null): MiddlewareFactoryInterface
Expand Down

0 comments on commit 3591c4c

Please sign in to comment.