Files
ABSDEV/Modules/Developer/Support/CrudGenerator.php
T
2026-07-24 14:59:44 +01:00

70 lines
4.4 KiB
PHP

<?php
namespace Modules\Developer\Support;
final class CrudGenerator extends Generator
{
public function generate(string $module, string $model, bool $force = false): array
{
$module = $this->studly($module);
$model = $this->studly($model);
$table = str($model)->plural()->snake()->toString();
$route = str($model)->plural()->kebab()->toString();
$root = rtrim(config('developer.modules_path', base_path('Modules')), '/').'/'.$module;
$timestamp = now()->format('Y_m_d_His');
$files = [
"$root/Models/{$model}.php" => $this->model($module, $model),
"$root/Http/Controllers/{$model}Controller.php" => $this->controller($module, $model),
"$root/Http/Requests/Store{$model}Request.php" => $this->request($module, $model),
"$root/Database/Migrations/{$timestamp}_create_{$table}_table.php" => $this->migration($table),
"$root/Resources/views/admin/{$route}/index.blade.php" => $this->indexView($model, $route),
"$root/Resources/views/admin/{$route}/form.blade.php" => $this->formView($model),
"$root/Tests/Feature/{$model}CrudTest.php" => $this->crudTest($module, $model),
];
foreach ($files as $path => $contents) {
$this->write($path, $contents, $force);
}
return array_keys($files);
}
private function model(string $module, string $model): string
{
return "<?php\n\nnamespace Modules\\{$module}\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nfinal class {$model} extends Model\n{\n protected \$guarded = [];\n\n protected function casts(): array\n {\n return ['is_active' => 'boolean'];\n }\n}\n";
}
private function controller(string $module, string $model): string
{
$plural = str($model)->plural()->kebab();
return "<?php\n\nnamespace Modules\\{$module}\\Http\\Controllers;\n\nuse Illuminate\\Http\\RedirectResponse;\nuse Illuminate\\View\\View;\nuse Modules\\{$module}\\Http\\Requests\\Store{$model}Request;\nuse Modules\\{$module}\\Models\\{$model};\n\nfinal class {$model}Controller\n{\n public function index(): View\n {\n return view('".str($module)->snake()."::admin.{$plural}.index', ['records' => {$model}::query()->latest()->paginate()]);\n }\n\n public function store(Store{$model}Request \$request): RedirectResponse\n {\n {$model}::query()->create(\$request->validated());\n return back()->with('status', '{$model} created.');\n }\n}\n";
}
private function request(string $module, string $model): string
{
return "<?php\n\nnamespace Modules\\{$module}\\Http\\Requests;\n\nuse Illuminate\\Foundation\\Http\\FormRequest;\n\nfinal class Store{$model}Request extends FormRequest\n{\n public function authorize(): bool { return \$this->user() !== null; }\n public function rules(): array { return ['name' => ['required', 'string', 'max:255'], 'is_active' => ['sometimes', 'boolean']]; }\n}\n";
}
private function migration(string $table): string
{
return "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nreturn new class extends Migration {\n public function up(): void { Schema::create('{$table}', function (Blueprint \$table): void { \$table->id(); \$table->string('name'); \$table->boolean('is_active')->default(true); \$table->timestamps(); }); }\n public function down(): void { Schema::dropIfExists('{$table}'); }\n};\n";
}
private function indexView(string $model, string $route): string
{
return "<x-layouts.app :title=\"__('{$model}')\">\n <div class=\"space-y-6\"><h1 class=\"text-2xl font-semibold\">{$model}</h1>@foreach (\$records as \$record)<div>{{ \$record->name }}</div>@endforeach{{ \$records->links() }}</div>\n</x-layouts.app>\n";
}
private function formView(string $model): string
{
return "<form method=\"POST\">@csrf<flux:input name=\"name\" :label=\"__('Name')\" required /><flux:button type=\"submit\" variant=\"primary\">{{ __('Save {$model}') }}</flux:button></form>\n";
}
private function crudTest(string $module, string $model): string
{
return "<?php\n\nuse Modules\\{$module}\\Models\\{$model};\n\nit('can create a {$model}', function (): void { expect({$model}::query()->create(['name' => 'Example']))->toBeInstanceOf({$model}::class); });\n";
}
}