feat: add module generator feature with controller, routing, and UI integration
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Types;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class ModuleGeneratorController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('admin.module-generator');
|
||||
}
|
||||
|
||||
public function generate(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'title' => 'required|string|max:255',
|
||||
'columns' => 'required|array',
|
||||
'columns.*.name' => 'required|string',
|
||||
'columns.*.type' => 'required|string',
|
||||
]);
|
||||
|
||||
$title = $request->title;
|
||||
$slug = Str::slug($title);
|
||||
$tableName = str_replace('-', '_', $slug);
|
||||
$modelName = Str::studly($slug);
|
||||
|
||||
// 1. Create Migration File
|
||||
$timestamp = date('Y_m_d_His');
|
||||
$migrationFilename = "{$timestamp}_create_{$tableName}_table.php";
|
||||
$migrationPath = database_path("migrations/{$migrationFilename}");
|
||||
|
||||
$migrationContent = "<?php\n\nuse Illuminate\Database\Migrations\Migration;\nuse Illuminate\Database\Schema\Blueprint;\nuse Illuminate\Support\Facades\Schema;\n\nclass Create" . Str::studly($tableName) . "Table extends Migration\n{\n public function up()\n {\n Schema::create('{$tableName}', function (Blueprint \$table) {\n \$table->id();\n";
|
||||
|
||||
foreach ($request->columns as $column) {
|
||||
$colName = Str::snake($column['name']);
|
||||
$uiType = $column['type'];
|
||||
|
||||
$dbType = 'string';
|
||||
switch ($uiType) {
|
||||
case 'integer': $dbType = 'integer'; break;
|
||||
case 'decimal': $dbType = 'decimal'; break;
|
||||
case 'date': $dbType = 'date'; break;
|
||||
case 'datetime': $dbType = 'dateTime'; break;
|
||||
case 'long-text': $dbType = 'longText'; break;
|
||||
case 'boolean': $dbType = 'boolean'; break;
|
||||
default: $dbType = 'string'; break;
|
||||
}
|
||||
|
||||
if ($dbType == 'decimal') {
|
||||
$migrationContent .= " \$table->decimal('{$colName}', 15, 2)->nullable();\n";
|
||||
} else {
|
||||
$migrationContent .= " \$table->{$dbType}('{$colName}')->nullable();\n";
|
||||
}
|
||||
}
|
||||
|
||||
$migrationContent .= " \$table->timestamps();\n \$table->softDeletes();\n });\n }\n\n public function down()\n {\n Schema::dropIfExists('{$tableName}');\n }\n}\n";
|
||||
|
||||
File::put($migrationPath, $migrationContent);
|
||||
|
||||
// Run the specific migration
|
||||
Artisan::call('migrate', [
|
||||
'--path' => "database/migrations/{$migrationFilename}",
|
||||
'--force' => true
|
||||
]);
|
||||
|
||||
// 2. Create Model
|
||||
$modelPath = app_path("Models/{$modelName}.php");
|
||||
if (!File::exists($modelPath)) {
|
||||
$modelContent = "<?php\n\nnamespace App\Models;\n\nuse Illuminate\Database\Eloquent\Model;\nuse Illuminate\Database\Eloquent\SoftDeletes;\n\nclass {$modelName} extends Model\n{\n use SoftDeletes;\n protected \$table = '{$tableName}';\n protected \$guarded = [];\n}\n";
|
||||
File::put($modelPath, $modelContent);
|
||||
}
|
||||
|
||||
// 3. Create Blade View
|
||||
$viewPath = resource_path("views/admin/type/{$slug}.blade.php");
|
||||
if (!File::exists($viewPath)) {
|
||||
$templatePath = resource_path("views/admin/type/datagrid-module-template.blade.php");
|
||||
if (File::exists($templatePath)) {
|
||||
$templateContent = File::get($templatePath);
|
||||
|
||||
// Simple replacements in template
|
||||
$templateContent = str_replace('use App\Models\RadiographicTest;', "use App\Models\\{$modelName};", $templateContent);
|
||||
$templateContent = str_replace('$title = "Radiographic Test";', "\$title = \"{$title}\";", $templateContent);
|
||||
$templateContent = str_replace('$tableName = "radiographic_tests";', "\$tableName = \"{$tableName}\";", $templateContent);
|
||||
|
||||
// Generate relationDatas
|
||||
$relationDatasCode = "\$relationDatas = [\n";
|
||||
foreach ($request->columns as $column) {
|
||||
$colName = Str::snake($column['name']);
|
||||
$colType = $column['type'];
|
||||
$relationDatasCode .= " '{$colName}' => [\n 'type' => '{$colType}',\n ],\n";
|
||||
}
|
||||
$relationDatasCode .= "];";
|
||||
|
||||
// Replace the hardcoded relationDatas in template
|
||||
$pattern = '/\$relationDatas = \[.*?\];/s';
|
||||
$templateContent = preg_replace($pattern, $relationDatasCode, $templateContent);
|
||||
|
||||
File::put($viewPath, $templateContent);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Handle Icon
|
||||
$iconName = $slug;
|
||||
if ($request->hasFile('icon')) {
|
||||
$request->file('icon')->move(base_path('assets/icons'), $iconName . '.png');
|
||||
}
|
||||
|
||||
// 5. Insert into types table
|
||||
$type = Types::where('slug', $slug)->first();
|
||||
if (!$type) {
|
||||
$type = new Types();
|
||||
$type->title = $title;
|
||||
$type->slug = $slug;
|
||||
$type->icon = $iconName;
|
||||
$type->enabled = 1;
|
||||
$type->full_control = "1"; // Default admin level
|
||||
$type->write = "1";
|
||||
$type->read = "1";
|
||||
$type->modify = "1";
|
||||
$type->save();
|
||||
}
|
||||
|
||||
return redirect("admin/types/{$slug}")->with('success', 'Module generated successfully!');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user