Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
5f09cad
feat(generation): add `ClassGenerator`
innocenzi Oct 5, 2024
8994764
:sparkles: Add NamespaceHelper class
gturpin-dev Oct 11, 2024
ee44096
:sparkles: Working version of the make:controller command
gturpin-dev Oct 11, 2024
76063f4
:art: Format code
gturpin-dev Oct 14, 2024
1023fdc
:fire: Comment breaking test from unmerged branch
gturpin-dev Oct 14, 2024
a487fe2
feat: add ability to publish vendor files
innocenzi Oct 2, 2024
8bb0f99
fix(path-helper): pass paths to `root`
innocenzi Oct 2, 2024
d9ee3d9
feat: add `getFilePath` to `ClassReflector`
innocenzi Oct 2, 2024
089f694
refactor: use `ClassReflector`
innocenzi Oct 2, 2024
912f23e
feat(publish): use `Composer` util to generate default publish paths
innocenzi Oct 2, 2024
7052427
feat(path-helper): add `toNamespace` and `toRegisteredNamespace`
innocenzi Oct 4, 2024
3953165
feat: mark migrations as publishable
innocenzi Oct 4, 2024
c8737ad
refactor: rename `publishFiles` to `publishClasses`
innocenzi Oct 4, 2024
1d7a424
feat(publish): remove attributes and update namespace of published cl…
innocenzi Oct 4, 2024
a26ae6a
test: fix assumption about migrations being registered
innocenzi Oct 4, 2024
8ad5b76
style: apply fixes from rector
innocenzi Oct 4, 2024
03ad829
feat: support publishing files
innocenzi Oct 11, 2024
d81a302
:recycle: Refactor make:controller using ToNamespace helper from Path…
gturpin-dev Oct 14, 2024
b701dee
:fire: Delete useless NamespaceHelper duplicates
gturpin-dev Oct 14, 2024
98c08e9
:sparkles: Add the toClassname() method for the PathHelper
gturpin-dev Oct 14, 2024
eddc8be
:pencil: Fix typo in PathHelper method name
gturpin-dev Oct 14, 2024
c8a483a
:recycle: Refactor the make:controller command to act more like publi…
gturpin-dev Oct 14, 2024
0849e0d
:recycle: Refactor the command to remove unnecessary manipulations
gturpin-dev Oct 14, 2024
b88d67c
:sparkles: Add replacements for path and view name in the make:contro…
gturpin-dev Oct 14, 2024
ecdfecb
:art: Prepare generator command abstraction skeleton
gturpin-dev Oct 15, 2024
6f94a6d
:bug: Allow TypeReflector to get null value
gturpin-dev Oct 15, 2024
8a4dc32
:sparkles: Implement the GeneratorCommand and the Discovery to discov…
gturpin-dev Oct 15, 2024
c755523
:recycle: Refactor the GeneratorCommand to extends from ConsoleCommand
gturpin-dev Oct 15, 2024
4594bb6
:sparkles: Implement the trait's methods
gturpin-dev Oct 15, 2024
872757c
:sparkles: Handle specific handlers for generator commands
gturpin-dev Oct 16, 2024
9e2127a
:sparkles: Make the StubFileGenerator logic
gturpin-dev Oct 16, 2024
fed3dae
:sparkles: conditionally generate model stub
gturpin-dev Oct 16, 2024
5e5aebe
:sparkles: Make Generator commands with multiple handler and generato…
gturpin-dev Oct 21, 2024
56e5b7d
:fire: Revert unwanted changes for now
gturpin-dev Oct 21, 2024
e6d78b8
:recycle: Refactor factory to GeneratorCommand specific method
gturpin-dev Oct 21, 2024
cf9de26
:art: Coding styles
gturpin-dev Oct 22, 2024
af2af0b
:rotating_light: Fix phpstan
gturpin-dev Oct 22, 2024
900a57f
:bug: Fix unused variable issue
gturpin-dev Oct 22, 2024
925aa11
:recycle: Refactor make:controller command to use the new generator api
gturpin-dev Oct 22, 2024
c396bff
:bug: Fix basics command issue
gturpin-dev Oct 22, 2024
6f45e99
:bug: Fix issues in make:controller command and dummy replacements
gturpin-dev Oct 22, 2024
39b0ca9
:art: Coding styles
gturpin-dev Oct 22, 2024
e3e9ce0
:sparkles: Allow php-http/discovery
gturpin-dev Oct 28, 2024
a3e8b84
:bug: Fix phpstan config issue
gturpin-dev Oct 28, 2024
82eabdb
:fire: Remove feat/publish dependency
gturpin-dev Oct 28, 2024
3c94f12
:bug: Fix issue
gturpin-dev Oct 28, 2024
2634717
:rotating_light: Run Rector
gturpin-dev Oct 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,5 +150,10 @@
"composer phpunit",
"composer phpstan"
]
},
"config": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove this? To make sure it doesn't get added again, rebase or merge main into your branch, then run composer up once more.

"allow-plugins": {
"php-http/discovery": true
}
}
}
71 changes: 37 additions & 34 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
includes:
- phpstan-baseline.neon
- vendor/phpat/phpat/extension.neon
- vendor/spaze/phpstan-disallowed-calls/extension.neon
- phpstan-baseline.neon
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why these changes?

- vendor/phpat/phpat/extension.neon
- vendor/spaze/phpstan-disallowed-calls/extension.neon
services:
-
class: Tests\Tempest\Architecture\ArchitectureTestCase
tags:
- phpat.test
-
class: Tests\Tempest\Architecture\ArchitectureTestCase
tags:
- phpat.test
parameters:
level: 5
tmpDir: .cache/phpstan
excludePaths:
- tests/Integration/View/blade/cache/**.php
paths:
- src
- tests
ignoreErrors:
level: 5
tmpDir: .cache/phpstan
excludePaths:
- tests/Integration/View/blade/cache/**.php
paths:
- src
- tests
ignoreErrors:

-
message: '#.*#'
path: src/Tempest/Http/src/Exceptions/exception.php
-
message: '#.*exec*#'
path: src/Tempest/Console/src/Terminal/Terminal.php
-
message: '#.*#'
path: src/Tempest/Http/src/Exceptions/exception.php
-
message: '#.*exec*#'
path: src/Tempest/Console/src/Terminal/Terminal.php
-
message: "#^Tempest\\\\Console\\\\ConsoleCommand should be final$#"
path: src/Tempest/Console/src/ConsoleCommand.php

disallowedFunctionCalls:
-
function: 'exec()'
-
function: 'eval()'
-
function: 'dd()'
-
function: 'dump()'
-
function: 'phpinfo()'
-
function: 'var_dump()'
disallowedFunctionCalls:
-
function: 'exec()'
-
function: 'eval()'
-
function: 'dd()'
-
function: 'dump()'
-
function: 'phpinfo()'
-
function: 'var_dump()'
25 changes: 15 additions & 10 deletions src/Tempest/Console/src/Actions/ExecuteConsoleCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
namespace Tempest\Console\Actions;

use Closure;
use RuntimeException;
use Tempest\Console\ConsoleConfig;
use Tempest\Console\ConsoleInputBuilder;
use Tempest\Console\ExitCode;
use Tempest\Console\GeneratorCommand;
use Tempest\Console\Initializers\Invocation;
use Tempest\Console\Input\ConsoleArgumentBag;
use Tempest\Container\Container;
use Tempest\Reflection\MethodReflector;

final readonly class ExecuteConsoleCommand
{
Expand All @@ -36,17 +39,19 @@ private function getCallable(array $commandMiddleware): Closure
{
$callable = function (Invocation $invocation) {
$consoleCommand = $invocation->consoleCommand;

$handler = $consoleCommand->handler;

$consoleCommandClass = $this->container->get($handler->getDeclaringClass()->getName());

$inputBuilder = new ConsoleInputBuilder($consoleCommand, $invocation->argumentBag);

$consoleCommand->handler->invokeArgs(
$consoleCommandClass,
$inputBuilder->build(),
);
$handler = ($consoleCommand instanceof GeneratorCommand)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this is the right way to go. I'd be very hesitant making changes within ExecuteConsoleCommand to accomodate for one specific command.

I still need to read through the rest though

? $consoleCommand->makeHandler()
: $consoleCommand->handler;

match (true) {
is_callable($handler) => $handler($inputBuilder->build()),
($handler instanceof MethodReflector) => $handler->invokeArgs(
$this->container->get($handler->getDeclaringClass()->getName()),
$inputBuilder->build()
),
default => throw new RuntimeException('Command handler cannot be resolved.'), // @phpstan-ignore-line
};

return ExitCode::SUCCESS;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

declare(strict_types=1);

namespace Tempest\Console\Commands\Generators;

use Tempest\Console\ConsoleArgument;
use Tempest\Console\GeneratorCommand;
use Tempest\Console\Stubs\ControllerStub;
use Tempest\Generation\HasGeneratorCommand;
use Tempest\Generation\StubFileGenerator;

final class MakeControllerCommand
{
use HasGeneratorCommand;

#[GeneratorCommand(
name : 'make:controller',
description: 'Create a new controller class with a basic route',
aliases : ['controller:make', 'controller:create', 'create:controller'],
)]
public function __invoke(
#[ConsoleArgument(
help: 'The name of the controller class to create ( "Controller" will be suffixed )',
)]
string $className,
?string $controllerPath = null,
?string $controllerView = null,
): StubFileGenerator {
$suggestedPath = $this->getSuggestedPath(
className : $className,
pathPrefix : 'Controllers',
classSuffix: 'Controller',
);
$targetPath = $this->promptTargetPath($suggestedPath);
$shouldOverride = $this->askForOverride($targetPath);

return new StubFileGenerator(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this briefly on Discord: I'm not convinced yet that we need a special kind of console commands that return a special kind of class. I rather just inject the generator into the console command.

Take, for example, a look at how the install command works: it doesn't need to return anything special, but rather passes the responsibility of actually installing a package to the underlying Installer class.

stubFile : ControllerStub::class,
targetPath : $targetPath,
shouldOverride: $shouldOverride,
replacements : [
'dummy-path' => $controllerPath,
'dummy-view' => $controllerView,
],
);
}
}
47 changes: 47 additions & 0 deletions src/Tempest/Console/src/Commands/Generators/MakeModelCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace Tempest\Console\Commands\Generators;

use Tempest\Console\ConsoleArgument;
use Tempest\Console\GeneratorCommand;
use Tempest\Console\Stubs\DatabaseModelStub;
use Tempest\Console\Stubs\ModelStub;
use Tempest\Generation\HasGeneratorCommand;
use Tempest\Generation\StubFileGenerator;

final class MakeModelCommand
{
use HasGeneratorCommand;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trait should be renamed to IsGeneratorCommand


#[GeneratorCommand(
name : 'make:model',
description: 'Create a new model class',
aliases : ['model:make', 'model:create', 'create:model'],
)]
public function __invoke(
#[ConsoleArgument(
help: 'The name of the model class to create ( "Model" will be suffixed )',
)]
string $className,
#[ConsoleArgument(
help: 'Whether the model is a database model',
)]
bool $isDatabaseModel = false,
): StubFileGenerator {
$suggestedPath = $this->getSuggestedPath(
className : $className,
pathPrefix : 'Models',
classSuffix: 'Model',
);
$targetPath = $this->promptTargetPath($suggestedPath);
$shouldOverride = $this->askForOverride($targetPath);

return new StubFileGenerator(
stubFile : $isDatabaseModel ? DatabaseModelStub::class : ModelStub::class,
targetPath : $targetPath,
shouldOverride: $shouldOverride,
);
}
}
2 changes: 1 addition & 1 deletion src/Tempest/Console/src/ConsoleCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Tempest\Reflection\MethodReflector;

#[Attribute]
final class ConsoleCommand
class ConsoleCommand
{
public MethodReflector $handler;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Tempest\Console\ConsoleCommand;
use Tempest\Console\ConsoleConfig;
use Tempest\Console\GeneratorCommand;
use Tempest\Container\Container;
use Tempest\Core\Discovery;
use Tempest\Core\HandlesDiscoveryCache;
Expand Down Expand Up @@ -41,7 +42,7 @@ public function createCachePayload(): string

public function restoreCachePayload(Container $container, string $payload): void
{
$commands = unserialize($payload, ['allowed_classes' => [ConsoleCommand::class, MethodReflector::class]]);
$commands = unserialize($payload, ['allowed_classes' => [GeneratorCommand::class, ConsoleCommand::class, MethodReflector::class]]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the reasons I'm hesitant about "a special kind of command class": we need several changes all over the place to make sure they work. That leads to a brittle and complicated design.


$this->consoleConfig->commands = $commands;
}
Expand Down
39 changes: 39 additions & 0 deletions src/Tempest/Console/src/GeneratorCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Tempest\Console;

use Attribute;
use Closure;
use Tempest\Generation\StubFileGenerator;
use function Tempest\get;
use function Tempest\Support\arr;

/**
* Defines a console command that is specifically for generating files.
*/
#[Attribute(Attribute::TARGET_METHOD)]
final class GeneratorCommand extends ConsoleCommand
{
/**
* Make the handler for the given command.
* This allow the console to run this handler without altering the command structure.
*
* @return Closure(array<mixed> $params) The command handler.
*/
public function makeHandler(): Closure
{
return function (array $params): void {
// Resolve all generators and run them.
arr(
$this->handler->invokeArgs(
get($this->handler->getDeclaringClass()->getName()),
$params
)
)
->filter(fn ($generator) => $generator instanceof StubFileGenerator)
->each(fn (StubFileGenerator $generator) => $generator->generate());
};
}
}
18 changes: 18 additions & 0 deletions src/Tempest/Console/src/Stubs/ControllerStub.php
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\Http\Get;
use function Tempest\view;
use Tempest\View\View;

final class ControllerStub
{
#[Get(uri: '/dummy-path')]
public function __invoke(): View
{
return view('dummy-view');
}
}
20 changes: 20 additions & 0 deletions src/Tempest/Console/src/Stubs/DatabaseModelStub.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace Tempest\Console\Stubs;

use Tempest\Database\DatabaseModel;
use Tempest\Database\IsDatabaseModel;
use Tempest\Validation\Rules\Length;

final class DatabaseModelStub implements DatabaseModel
{
use IsDatabaseModel;

public function __construct(
#[Length(min: 1, max: 120)]
public string $title
) {
}
}
16 changes: 16 additions & 0 deletions src/Tempest/Console/src/Stubs/ModelStub.php
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\Validation\Rules\Length;

final class ModelStub
{
public function __construct(
#[Length(min: 1, max: 120)]
public string $title
) {
}
}
2 changes: 2 additions & 0 deletions src/Tempest/Database/src/Migrations/CreateMigrationsTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

namespace Tempest\Database\Migrations;

use Tempest\Core\DoNotDiscover;
use Tempest\Database\Migration;
use Tempest\Database\Migrations\Migration as Model;
use Tempest\Database\QueryStatement;
use Tempest\Database\QueryStatements\CreateTableStatement;
use Tempest\Database\QueryStatements\DropTableStatement;

#[DoNotDiscover]
final readonly class CreateMigrationsTable implements Migration
{
public function getName(): string
Expand Down
Loading