Skip to content

Commit 7d73e9a

Browse files
authored
Merge pull request #3 from mhQady/dev
add console command to create action class
2 parents 39ed5d5 + 564137d commit 7d73e9a

11 files changed

Lines changed: 129 additions & 171 deletions

src/Actions/ActionRunner.php

Lines changed: 0 additions & 89 deletions
This file was deleted.

src/Console/ListWorkflow.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Flowra\Console;
44

5+
use App\Workflows\Actions\NotifyUserAction;
56
use App\Workflows\Guards\OnlyAdminGuard;
67
use Flowra\Flows\MainFlow\MainWorkflowStates;
78
use Flowra\Models\Context;
@@ -25,7 +26,7 @@ public function handle()
2526
$t = $flow->mainWorkflow->fillingOwnerDataTransition->guard(function (): bool {
2627
dump('guard 1 evaluating...');
2728
return true;
28-
}, new OnlyAdminGuard())->action(fn() => dump('action executing...'))->apply();
29+
}, new OnlyAdminGuard())->action(fn() => dump('action executing...'), NotifyUserAction::class)->apply();
2930

3031
dd('transition applied successfully 🎉');
3132
// $t = $flow->mainFlow->jump(MainWorkflowStates::SENT_BACK_TO_SURVEYOR_FOR_REVISION);

src/Console/MakeAction.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Flowra\Console;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Filesystem\Filesystem;
7+
use Illuminate\Support\Str;
8+
9+
class MakeAction extends Command
10+
{
11+
protected $signature = 'flowra:make-action
12+
{name : Action name, e.g. NotifyUser}
13+
{--path=app/Workflows/Actions : Directory where the action will be created}
14+
{--namespace=App\\Workflows\\Actions : Namespace for the generated class}
15+
{--force : Overwrite if the file already exists}';
16+
17+
protected $description = 'Create a new Flowra action class.';
18+
19+
public function handle(Filesystem $files): int
20+
{
21+
// Normalize name → ensure it ends with "Action"
22+
$raw = trim($this->argument('name'));
23+
$studly = Str::studly($raw);
24+
if (!Str::endsWith($studly, 'Action')) {
25+
$studly .= 'Action';
26+
}
27+
28+
// Resolve paths & namespace
29+
$basePath = base_path(Str::finish($this->option('path'), '/'));
30+
$namespace = rtrim($this->option('namespace'), '\\');
31+
$filename = $basePath.$studly.'.php';
32+
$class = $studly;
33+
34+
if (!$files->isDirectory($basePath)) {
35+
$files->makeDirectory($basePath, 0777, true);
36+
}
37+
38+
// Load stub (published first, then package fallback)
39+
$stub = $this->getStub('action.stub');
40+
41+
// Render
42+
$rendered = strtr($stub, [
43+
'{{ namespace }}' => $namespace,
44+
'{{ class }}' => $class,
45+
]);
46+
47+
// Write
48+
if ($files->exists($filename) && !$this->option('force')) {
49+
$this->warn("⏭ Skipped (exists): {$filename} (use --force to overwrite)");
50+
return self::SUCCESS;
51+
}
52+
53+
$files->put($filename, $rendered);
54+
$this->info("✅ Action generated: {$namespace}\\{$class}");
55+
$this->line(" • Wrote: <info>{$filename}</info>");
56+
57+
return self::SUCCESS;
58+
}
59+
60+
private function getStub(string $name): string
61+
{
62+
$name = ltrim($name, '/\\');
63+
64+
// 1) app-published stubs take precedence
65+
$appStub = base_path('stubs/flowra/'.$name);
66+
if (is_file($appStub)) {
67+
$data = file_get_contents($appStub);
68+
if ($data !== false) {
69+
return $data;
70+
}
71+
}
72+
73+
// 2) package default stub (src/stubs/action.stub)
74+
$packageStub = dirname(__DIR__, 1).'/stubs/'.$name; // __DIR__ = src/Console
75+
if (is_file($packageStub)) {
76+
$data = file_get_contents($packageStub);
77+
if ($data !== false) {
78+
return $data;
79+
}
80+
}
81+
82+
throw new \RuntimeException("Stub not found: {$name}\nLooked in:\n - {$appStub}\n - {$packageStub}");
83+
}
84+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
use RuntimeException;
88
use Str;
99

10-
class GenerateWorkflow extends Command
10+
class MakeWorkflow extends Command
1111
{
12-
protected $signature = 'flowra:generate
12+
protected $signature = 'flowra:make-workflow
1313
{name : Workflow name, e.g. Main}
1414
{--path=app/Workflows : Base directory where the workflow folder will be created}
1515
{--namespace=App\\Workflows : Root namespace for generated classes}

src/FlowraServiceProvider.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ public function boot(): void
1212
{
1313
if ($this->app->runningInConsole()) {
1414
$this->commands([
15-
\Flowra\Console\GenerateWorkflow::class,
16-
\Flowra\Console\ListWorkflow::class,
15+
\Flowra\Console\MakeWorkflow::class,
1716
\Flowra\Console\MakeGuard::class,
17+
\Flowra\Console\MakeAction::class,
18+
\Flowra\Console\ListWorkflow::class,
1819
]);
1920
}
2021

@@ -32,7 +33,7 @@ public function boot(): void
3233
__DIR__.'/stubs' => base_path('stubs/flowra'),
3334
], 'flowra-stubs');
3435

35-
AboutCommand::add('Flowra', fn () => [
36+
AboutCommand::add('Flowra', fn() => [
3637
'Version' => InstalledVersions::getPrettyVersion('mhqady/flowra')
3738
]);
3839
}

src/Traits/CanApplyTransitions.php

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,13 @@ trait CanApplyTransitions
2121
*/
2222
public function apply(Transition $t, ?array $comment = null): static
2323
{
24-
dump('guard start evaluation 🏁');
2524
$this->__evaluateGuards($t);
26-
dump('guard ends evaluation ⚰');
2725

28-
dump('validation started 🏁');
2926
$this->__validateTransitionApplicable($t);
30-
dump('validation ended ⚰');
3127

32-
dump('saving started 🏁');
33-
// $this->__save($t, $comment);
34-
dump('saving ended ⚰');
28+
$this->__save($t, $comment);
3529

36-
dump('running actions started 🏁');
37-
$this->run($t);
38-
dump('running actions ended ⚰');
30+
$this->__executeActions($t);
3931

4032
return $this;
4133
}

src/Traits/CanExecuteActions.php

Lines changed: 12 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,23 @@
22

33
namespace Flowra\Traits;
44

5-
use Flowra\Actions\ActionRunner;
5+
use Flowra\Contracts\ActionContract;
66
use Flowra\DTOs\Transition;
7-
use Illuminate\Support\Facades\App;
87

98
trait CanExecuteActions
109
{
11-
public function run(Transition $t): void
10+
private function __executeActions(Transition $t): void
1211
{
13-
App::make(ActionRunner::class)->run($t->actions());
12+
foreach ($t->actions() as $action) {
1413

15-
// $context['when'] ??= Carbon::now();
16-
//
17-
// foreach ($actions as $action) {
18-
// // Closure
19-
// if ($action instanceof Closure) {
20-
// $action($context);
21-
// continue;
22-
// }
23-
//
24-
// // ['Class', params] or 'Class'
25-
// [$class, $params] = is_array($action)
26-
// ? [$action[0], (array) ($action[1] ?? [])]
27-
// : [$action, []];
28-
//
29-
// $instance = App::make($class, $params);
30-
//
31-
// // If the class is invokable, prefer __invoke(array $context)
32-
// if (is_callable($instance)) {
33-
// $callable = $instance;
34-
// // Queue if the class signals ShouldQueue
35-
// if ($instance instanceof ShouldQueue) {
36-
// $this->bus->dispatch(function () use ($callable, $context) {
37-
// $callable($context);
38-
// });
39-
// } else {
40-
// $callable($context);
41-
// }
42-
// continue;
43-
// }
44-
//
45-
// // If it implements our contract
46-
// if ($instance instanceof TransitionAction) {
47-
// if ($instance instanceof ShouldQueue) {
48-
// // Dispatch to queue via Bus to keep things simple
49-
// $this->bus->dispatch(new class($instance, $context) implements ShouldQueue {
50-
// public function __construct(public TransitionAction $action, public array $context)
51-
// {
52-
// }
53-
//
54-
// public function handle(): void
55-
// {
56-
// $this->action->handle($this->context);
57-
// }
58-
// });
59-
// } else {
60-
// $instance->handle($context);
61-
// }
62-
// continue;
63-
// }
64-
//
65-
// // Fallback: method 'handle' if present
66-
// if (method_exists($instance, 'handle')) {
67-
// $instance->handle($context);
68-
// continue;
69-
// }
70-
//
71-
// throw new \InvalidArgumentException("Unsupported action type for: ".(is_string($class) ? $class : get_debug_type($action)));
72-
// }
14+
$instance = $action;
15+
16+
if (is_string($action)) {
17+
$instance = app($action);
18+
}
19+
20+
$instance instanceof ActionContract ? $instance->execute($t) : $instance($t);
21+
22+
}
7323
}
7424
}

src/Traits/HasWorkflowRelations.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ protected static function bootHasWorkflowRelations(): void
1919

2020
private static function __registerWorkflowsRelations(): void
2121
{
22-
foreach ((new static)->workflows as $workflowClass) {
22+
$model = (new static);
23+
24+
$workflows = property_exists($model, 'workflows') ? $model->workflows : [];
25+
26+
foreach ($workflows as $workflowClass) {
2327

2428
$alias = Str::camel(class_basename($workflowClass));
2529

src/database/migrations/create_flowra_tables.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
return new class extends Migration {
99
public function up(): void
1010
{
11-
Schema::create(config('flowra.tables.statuses'), function (Blueprint $table) {
11+
Schema::create(config('flowra.tables.statuses', 'statuses'), function (Blueprint $table) {
1212
$table->id();
1313
$table->morphs('owner');
1414
$table->string('workflow');
@@ -21,7 +21,7 @@ public function up(): void
2121
$table->timestamps();
2222
});
2323

24-
Schema::create(config('flowra.tables.registry'), function (Blueprint $table) {
24+
Schema::create(config('flowra.tables.registry', 'statuses_registry'), function (Blueprint $table) {
2525
$table->id();
2626
$table->morphs('owner');
2727
$table->string('workflow');

src/stubs/action.stub

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace {{ namespace }};
4+
5+
use Flowra\Contracts\ActionContract;
6+
use Flowra\Flows\BaseWorkflow;
7+
use Flowra\DTOs\Transition;
8+
9+
class {{ class }} implements ActionContract
10+
{
11+
public function execute(Transition $t): void
12+
{
13+
//
14+
}
15+
}

0 commit comments

Comments
 (0)