-
-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(console): add
make:middleware
command (#804)
- Loading branch information
1 parent
0f47a80
commit 467c664
Showing
7 changed files
with
277 additions
and
0 deletions.
There are no files selected for viewing
68 changes: 68 additions & 0 deletions
68
src/Tempest/Console/src/Commands/MakeMiddlewareCommand.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Commands; | ||
|
||
use InvalidArgumentException; | ||
use Tempest\Console\ConsoleArgument; | ||
use Tempest\Console\ConsoleCommand; | ||
use Tempest\Console\Enums\MiddlewareType; | ||
use Tempest\Console\Stubs\CommandBusMiddlewareStub; | ||
use Tempest\Console\Stubs\ConsoleMiddlewareStub; | ||
use Tempest\Console\Stubs\EventBusMiddlewareStub; | ||
use Tempest\Console\Stubs\HttpMiddlewareStub; | ||
use Tempest\Core\PublishesFiles; | ||
use Tempest\Generation\DataObjects\StubFile; | ||
use Tempest\Generation\Exceptions\FileGenerationAbortedException; | ||
use Tempest\Generation\Exceptions\FileGenerationFailedException; | ||
|
||
final class MakeMiddlewareCommand | ||
{ | ||
use PublishesFiles; | ||
|
||
#[ConsoleCommand( | ||
name: 'make:middleware', | ||
description: 'Creates a new middleware class', | ||
aliases: ['middleware:make', 'middleware:create', 'create:middleware'], | ||
)] | ||
public function __invoke( | ||
#[ConsoleArgument( | ||
help: 'The name of the middleware class to create', | ||
)] | ||
string $className, | ||
#[ConsoleArgument( | ||
name: 'type', | ||
help: 'The type of the middleware to create', | ||
)] | ||
MiddlewareType $middlewareType, | ||
): void { | ||
try { | ||
$stubFile = $this->getStubFileFromMiddlewareType($middlewareType); | ||
$suggestedPath = $this->getSuggestedPath($className); | ||
$targetPath = $this->promptTargetPath($suggestedPath); | ||
$shouldOverride = $this->askForOverride($targetPath); | ||
|
||
$this->stubFileGenerator->generateClassFile( | ||
stubFile: $stubFile, | ||
targetPath: $targetPath, | ||
shouldOverride: $shouldOverride, | ||
); | ||
|
||
$this->success(sprintf('Middleware successfully created at "%s".', $targetPath)); | ||
} catch (FileGenerationAbortedException|FileGenerationFailedException|InvalidArgumentException $e) { | ||
$this->error($e->getMessage()); | ||
} | ||
} | ||
|
||
private function getStubFileFromMiddlewareType(MiddlewareType $middlewareType): StubFile | ||
{ | ||
return match ($middlewareType) { | ||
MiddlewareType::CONSOLE => StubFile::from(ConsoleMiddlewareStub::class), | ||
MiddlewareType::HTTP => StubFile::from(HttpMiddlewareStub::class), | ||
MiddlewareType::EVENT_BUS => StubFile::from(EventBusMiddlewareStub::class), | ||
MiddlewareType::COMMAND_BUS => StubFile::from(CommandBusMiddlewareStub::class), // @phpstan-ignore match.alwaysTrue (Because this is a guardrail for the future implementations) | ||
default => throw new InvalidArgumentException(sprintf('The "%s" middleware type has no supported stub file.', $middlewareType->value)), | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Enums; | ||
|
||
use Tempest\CommandBus\CommandBusMiddleware; | ||
use Tempest\Console\ConsoleMiddleware; | ||
use Tempest\EventBus\EventBusMiddleware; | ||
use Tempest\Router\HttpMiddleware; | ||
|
||
/** | ||
* Represents available middleware types in Tempest. | ||
*/ | ||
enum MiddlewareType: string | ||
{ | ||
case CONSOLE = 'console'; | ||
case HTTP = 'http'; | ||
case EVENT_BUS = 'event-bus'; | ||
case COMMAND_BUS = 'command-bus'; | ||
|
||
/** | ||
* Get the related interface for the middleware type. | ||
* | ||
* @return class-string | ||
*/ | ||
public function relatedInterface(): string | ||
{ | ||
return match ($this) { | ||
self::CONSOLE => ConsoleMiddleware::class, | ||
self::HTTP => HttpMiddleware::class, | ||
self::EVENT_BUS => EventBusMiddleware::class, | ||
self::COMMAND_BUS => CommandBusMiddleware::class, | ||
}; | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
src/Tempest/Console/src/Stubs/CommandBusMiddlewareStub.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Stubs; | ||
|
||
use Tempest\CommandBus\CommandBusMiddleware; | ||
use Tempest\CommandBus\CommandBusMiddlewareCallable; | ||
|
||
final class CommandBusMiddlewareStub implements CommandBusMiddleware | ||
{ | ||
public function __invoke(object $command, CommandBusMiddlewareCallable $next): void | ||
{ | ||
$next($command); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Stubs; | ||
|
||
use Tempest\Console\ConsoleMiddleware; | ||
use Tempest\Console\ConsoleMiddlewareCallable; | ||
use Tempest\Console\ExitCode; | ||
use Tempest\Console\HasConsole; | ||
use Tempest\Console\Initializers\Invocation; | ||
|
||
final class ConsoleMiddlewareStub implements ConsoleMiddleware | ||
{ | ||
use HasConsole; | ||
|
||
public function __invoke(Invocation $invocation, ConsoleMiddlewareCallable $next): ExitCode|int | ||
{ | ||
return $next($invocation); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Stubs; | ||
|
||
use Tempest\EventBus\EventBusMiddleware; | ||
use Tempest\EventBus\EventBusMiddlewareCallable; | ||
|
||
final class EventBusMiddlewareStub implements EventBusMiddleware | ||
{ | ||
public function __invoke(object $event, EventBusMiddlewareCallable $next): void | ||
{ | ||
$next($event); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tempest\Console\Stubs; | ||
|
||
use Tempest\Router\HttpMiddleware; | ||
use Tempest\Router\HttpMiddlewareCallable; | ||
use Tempest\Router\Request; | ||
use Tempest\Router\Response; | ||
|
||
final class HttpMiddlewareStub implements HttpMiddleware | ||
{ | ||
public function __invoke(Request $request, HttpMiddlewareCallable $next): Response | ||
{ | ||
return $next($request); | ||
} | ||
} |
102 changes: 102 additions & 0 deletions
102
tests/Integration/Console/Commands/MakeMiddlewareCommandTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Tests\Tempest\Integration\Console\Commands; | ||
|
||
use PHPUnit\Framework\Attributes\DataProvider; | ||
use PHPUnit\Framework\Attributes\Test; | ||
use Tempest\Console\Enums\MiddlewareType; | ||
use Tempest\Core\ComposerNamespace; | ||
use Tests\Tempest\Integration\FrameworkIntegrationTestCase; | ||
use function Tempest\Support\str; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
final class MakeMiddlewareCommandTest extends FrameworkIntegrationTestCase | ||
{ | ||
protected function setUp(): void | ||
{ | ||
parent::setUp(); | ||
|
||
$this->installer->configure( | ||
__DIR__ . '/install', | ||
new ComposerNamespace('App\\', __DIR__ . '/install/App'), | ||
); | ||
} | ||
|
||
protected function tearDown(): void | ||
{ | ||
$this->installer->clean(); | ||
|
||
parent::tearDown(); | ||
} | ||
|
||
#[DataProvider('command_input_provider')] | ||
#[Test] | ||
public function make_command( | ||
string $commandArgs, | ||
string $expectedPath, | ||
string $expectedNamespace, | ||
): void { | ||
$this->console | ||
->call("make:middleware {$commandArgs}") | ||
->submit(); | ||
|
||
$this->installer | ||
->assertFileExists($expectedPath) | ||
->assertFileContains($expectedPath, 'namespace ' . $expectedNamespace . ';'); | ||
} | ||
|
||
public static function command_input_provider(): array | ||
{ | ||
return [ | ||
'make_with_defaults' => [ | ||
'commandArgs' => 'BookMiddleware http', | ||
'expectedPath' => 'App/BookMiddleware.php', | ||
'expectedNamespace' => 'App', | ||
], | ||
'make_with_other_namespace' => [ | ||
'commandArgs' => 'Middlewares\\BookMiddleware http', | ||
'expectedPath' => 'App/Middlewares/BookMiddleware.php', | ||
'expectedNamespace' => 'App\\Middlewares', | ||
], | ||
'make_with_input_path' => [ | ||
'commandArgs' => 'Middlewares/BookMiddleware http', | ||
'expectedPath' => 'App/Middlewares/BookMiddleware.php', | ||
'expectedNamespace' => 'App\\Middlewares', | ||
], | ||
]; | ||
} | ||
|
||
#[DataProvider('middleware_type_provider')] | ||
#[Test] | ||
public function make_command_with_each_type( | ||
MiddlewareType $middlewareType, | ||
string $middlewareInterface, | ||
): void { | ||
$this->console | ||
->call("make:middleware TestMiddleware {$middlewareType->value}") | ||
->submit(); | ||
|
||
$filepath = 'App/TestMiddleware.php'; | ||
$middlewareInterface = str($middlewareInterface)->classBasename()->toString(); | ||
$this->installer | ||
->assertFileExists($filepath) | ||
->assertFileContains($filepath, 'implements ' . $middlewareInterface); | ||
} | ||
|
||
public static function middleware_type_provider(): array | ||
{ | ||
$cases = MiddlewareType::cases(); | ||
|
||
return array_combine( | ||
keys: array_map(fn (MiddlewareType $case) => $case->value, $cases), | ||
values: array_map(fn (MiddlewareType $case) => [ | ||
'middlewareType' => $case, | ||
'middlewareInterface' => $case->relatedInterface(), | ||
], $cases), | ||
); | ||
} | ||
} |