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 generator commands #262

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
24 changes: 24 additions & 0 deletions src/Commands/MakeAbstractStateCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Spatie\ModelStates\Commands;

use Illuminate\Console\GeneratorCommand;

class MakeAbstractStateCommand extends GeneratorCommand
{
public $name = 'make:abstract-state';

public $description = 'Create an abstract state class';

public $type = 'Abstract State';

protected function getStub(): string
{
return __DIR__ . '/../../stubs/abstract-state.stub';
}

protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace . '\Models\States';
}
}
58 changes: 58 additions & 0 deletions src/Commands/MakeStateCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace Spatie\ModelStates\Commands;

use Illuminate\Console\GeneratorCommand;
use Symfony\Component\Console\Input\InputArgument;

class MakeStateCommand extends GeneratorCommand
{
public $name = 'make:state';

public $description = 'Create a state class';

public $type = 'State';

protected function getStub(): string
{
return __DIR__ . '/../../stubs/state.stub';
}

protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace . '\Models\States';
}

protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)],
['parent', InputArgument::REQUIRED, 'The name of the parent abstract state'],
];
}

protected function buildClass($name)
{
$stub = $this->files->get($this->getStub());
$parent = $this->getParent();

return $this
->replaceNamespace($stub, $name)
->replaceParent($stub, $parent)
->replaceClass($stub, $name);
}

protected function replaceParent(&$stub, $name): self
{
$class = str_replace($this->getNamespace($name).'\\', '', $name);

$stub = str_replace(['DummyParent', '{{ parent }}', '{{parent}}'], $class, $stub);

return $this;
}

protected function getParent(): string
{
return trim($this->argument('parent'));
}
}
60 changes: 60 additions & 0 deletions src/Commands/MakeTransitionCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace Spatie\ModelStates\Commands;

use Illuminate\Console\GeneratorCommand;
use Illuminate\Support\Str;
use Symfony\Component\Console\Input\InputArgument;

class MakeTransitionCommand extends GeneratorCommand
{
public $name = 'make:transition';

public $description = 'Create a transition class';

public $type = 'Transition';

protected function getStub(): string
{
return __DIR__ . '/../../stubs/transition.stub';
}

protected function getDefaultNamespace($rootNamespace): string
{
return $rootNamespace . '\Models\States';
}

protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the '.strtolower($this->type)],
['parent', InputArgument::REQUIRED, 'The name of the model'],
];
}

protected function buildClass($name)
{
$stub = $this->files->get($this->getStub());
$parent = $this->getParent();

return $this
->replaceNamespace($stub, $name)
->replaceParent($stub, $parent)
->replaceClass($stub, $name);
}

protected function replaceParent(&$stub, $name): self
{
$class = str_replace($this->getNamespace($name).'\\', '', $name);

$stub = str_replace(['DummyParent', '{{ parent }}', '{{parent}}'], $class, $stub);
$stub = str_replace('model', Str::camel($class), $stub);

return $this;
}

protected function getParent(): string
{
return trim($this->argument('parent'));
}
}
8 changes: 8 additions & 0 deletions src/ModelStatesServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@

use Spatie\LaravelPackageTools\Package;
use Spatie\LaravelPackageTools\PackageServiceProvider;
use Spatie\ModelStates\Commands\MakeAbstractStateCommand;
use Spatie\ModelStates\Commands\MakeStateCommand;
use Spatie\ModelStates\Commands\MakeTransitionCommand;

class ModelStatesServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$package
->name('laravel-model-states')
->hasCommands([
MakeAbstractStateCommand::class,
MakeStateCommand::class,
MakeTransitionCommand::class,
])
->hasConfigFile();
}
}
10 changes: 10 additions & 0 deletions stubs/abstract-state.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace DummyNamespace;

use Spatie\ModelStates\State;

abstract class DummyClass extends State
{
//
}
8 changes: 8 additions & 0 deletions stubs/state.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace DummyNamespace;

class DummyClass extends DummyParent
{
//
}
28 changes: 28 additions & 0 deletions stubs/transition.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace DummyNamespace;

use App\Models\DummyParent;
use Spatie\ModelStates\Transition;

class DummyClass extends Transition
{
public function __construct
(
private readonly DummyParent $model,
) {
//
}

public function handle(): DummyParent
{
//

return $this->model;
}

public function canTransition(): bool
{
//
}
}
43 changes: 43 additions & 0 deletions tests/CommandsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

it('can generate abstract states', function () {
$file = $this->app->basePath('app/Models/States') . '/AbstractState.php';

$this->artisan('make:abstract-state AbstractState')->assertExitCode(0);

expect($file)
->toBeFile()
->toContainAsFile('class AbstractState extends State');

unlink($file);
});

it('can generate states', function () {
$file = $this->app->basePath('app/Models/States') . '/State.php';

$this->artisan('make:state State')
->expectsQuestion('What is the name of the parent abstract state?', 'AbstractState')
->assertExitCode(0);

expect($file)
->toBeFile()
->toContainAsFile('class State extends AbstractState');

unlink($file);
});

it('can generate transitions', function () {
$file = $this->app->basePath('app/Models/States') . '/CustomTransition.php';

$this->artisan('make:transition CustomTransition')
->expectsQuestion('What is the name of the model?', 'Model')
->assertExitCode(0);

expect($file)
->toBeFile()
->toContainAsFile('class CustomTransition extends Transition')
->toContainAsFile('private readonly Model $model,')
->toContainAsFile('return $this->model;');

unlink($file);
});
7 changes: 7 additions & 0 deletions tests/Pest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
|--------------------------------------------------------------------------
*/

expect()->extend('toContainAsFile', function ($needle) {
expect(file_get_contents($this->value))
->toContain($needle);

return $this;
});

/*
|--------------------------------------------------------------------------
| Functions
Expand Down
8 changes: 8 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Illuminate\Database\Schema\Blueprint;
use Orchestra\Testbench\TestCase as Orchestra;
use Spatie\ModelStates\ModelStatesServiceProvider;

abstract class TestCase extends Orchestra
{
Expand All @@ -14,6 +15,13 @@ protected function setUp(): void
$this->setUpDatabase();
}

protected function getPackageProviders($app)
{
return [
ModelStatesServiceProvider::class,
];
}

protected function getEnvironmentSetUp($app)
{
$app['config']->set('database.default', 'sqlite');
Expand Down
Loading