Files
citrus-cms/app/Http/Controllers/ModuleGeneratorController.php

171 lines
7.4 KiB
PHP

<?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()
{
$contents = \App\Contents::where("kid","main")->orderBy("s","ASC")->get();
return view('admin.module-generator', compact('contents'));
}
public function generate(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'columns' => 'required|array',
]);
$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) {
$uiType = $column['type'];
if ($uiType === 'separator') continue; // No column for separator
$colName = Str::snake($column['name']);
$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 'time': $dbType = 'time'; break;
case 'long-text': $dbType = 'longText'; break;
case 'boolean': $dbType = 'boolean'; break;
case 'multiple-choice': $dbType = 'text'; break; // Use text for multiple selection
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);
// Placeholder replacements
$templateContent = str_replace('[[MODEL_NAME]]', $modelName, $templateContent);
$templateContent = str_replace('[[TITLE]]', $title, $templateContent);
$templateContent = str_replace('[[TABLE_NAME]]', $tableName, $templateContent);
// Generate relationDatas
$relationDatasCode = "[\n";
foreach ($request->columns as $column) {
$uiType = $column['type'];
if ($uiType === 'separator') {
$label = $column['label'] ?? 'Separator';
$relationDatasCode .= " 'separator_" . rand(100, 999) . "' => [\n 'type' => 'separator',\n 'label' => '{$label}',\n ],\n";
continue;
}
$colName = Str::snake($column['name']);
$relationDatasCode .= " '{$colName}' => [\n 'type' => '{$uiType}',\n";
if ($uiType === 'select' || $uiType === 'multiple-choice') {
$optionsStr = $column['options'] ?? '';
$optionsArr = array_map('trim', explode(',', $optionsStr));
$relationDatasCode .= " 'datas' => [\n";
foreach ($optionsArr as $opt) {
if (empty($opt)) continue;
$relationDatasCode .= " ['id' => '{$opt}', 'name' => '{$opt}'],\n";
}
$relationDatasCode .= " ],\n";
if ($uiType === 'select') {
$relationDatasCode .= " 'value' => 'id',\n";
}
if ($uiType === 'multiple-choice') {
$relationDatasCode .= " 'pattern' => '{name}',\n";
$relationDatasCode .= " 'seperator' => ',',\n";
}
} elseif ($uiType === 'select-dropdown') {
$source = $column['source'] ?? '';
$relationDatasCode .= " 'dataSource' => '{$source}',\n";
$relationDatasCode .= " 'datas' => [],\n";
$relationDatasCode .= " 'pattern' => '{name}',\n";
}
$relationDatasCode .= " ],\n";
}
$relationDatasCode .= "]";
$templateContent = str_replace('[[RELATION_DATAS]]', $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";
$type->write = "1";
$type->read = "1";
$type->modify = "1";
$type->save();
}
return redirect("admin/types/{$slug}")->with('success', 'Module generated successfully!');
}
}