Skip to content

Commit e29bb61

Browse files
Merge pull request #2 from Relaticle/next
Implement upgrade command for Custom Fields plugin with database sche…
2 parents f3c8744 + 981a8b2 commit e29bb61

File tree

5 files changed

+262
-158
lines changed

5 files changed

+262
-158
lines changed
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
namespace Relaticle\CustomFields\Commands\Upgrade;
4+
5+
use Closure;
6+
use Illuminate\Database\Schema\Blueprint;
7+
use Illuminate\Support\Facades\Schema;
8+
use Relaticle\CustomFields\Commands\UpgradeCommand;
9+
use Relaticle\CustomFields\Support\Utils;
10+
use Illuminate\Console\Command;
11+
12+
class UpdateDatabaseSchema
13+
{
14+
public function handle(UpgradeCommand $command, Closure $next): mixed
15+
{
16+
$isDryRun = $command->isDryRun();
17+
18+
$command->info('--- Updating database schema...');
19+
$command->newLine();
20+
21+
// Logic to update database schema
22+
$this->createCustomFieldSectionsTable($command, $isDryRun);
23+
$this->updateCustomFieldsTable($command, $isDryRun);
24+
$this->removeDeletedAtColumns($command, $isDryRun);
25+
26+
$command->newLine();
27+
$command->info('Database schema update step completed.');
28+
$command->newLine();
29+
30+
return $next($command);
31+
}
32+
33+
private function createCustomFieldSectionsTable(Command $command, bool $isDryRun): void
34+
{
35+
$sectionsTable = config('custom-fields.table_names.custom_field_sections', 'custom_field_sections');
36+
37+
if (!Schema::hasTable($sectionsTable)) {
38+
if ($isDryRun) {
39+
$command->line("Table `{$sectionsTable}` would be created.");
40+
} else {
41+
Schema::create($sectionsTable, function (Blueprint $table): void {
42+
$table->id();
43+
if (Utils::isTenantEnabled()) {
44+
$table->foreignId(config('custom-fields.column_names.tenant_foreign_key'))->nullable()->index();
45+
}
46+
$table->string('code');
47+
$table->string('name');
48+
$table->string('type');
49+
$table->string('entity_type');
50+
$table->unsignedBigInteger('sort_order')->nullable();
51+
$table->string('description')->nullable();
52+
$table->boolean('active')->default(true);
53+
$table->boolean('system_defined')->default(false);
54+
55+
$uniqueColumns = ['entity_type', 'code'];
56+
if (Utils::isTenantEnabled()) {
57+
$uniqueColumns[] = config('custom-fields.column_names.tenant_foreign_key');
58+
}
59+
$table->unique($uniqueColumns);
60+
61+
$table->timestamps();
62+
});
63+
$command->info("Table `{$sectionsTable}` created successfully.");
64+
}
65+
} else {
66+
$command->line("Table `{$sectionsTable}` already exists. Skipping creation.");
67+
}
68+
}
69+
70+
private function updateCustomFieldsTable(Command $command, bool $isDryRun): void
71+
{
72+
$customFieldsTable = config('custom-fields.table_names.custom_fields');
73+
74+
$columnsToAdd = [];
75+
if (!Schema::hasColumn($customFieldsTable, 'custom_field_section_id')) {
76+
$columnsToAdd[] = 'custom_field_section_id';
77+
}
78+
if (!Schema::hasColumn($customFieldsTable, 'width')) {
79+
$columnsToAdd[] = 'width';
80+
}
81+
82+
if (!empty($columnsToAdd)) {
83+
if ($isDryRun) {
84+
foreach ($columnsToAdd as $column) {
85+
$command->line("Column `{$column}` would be added to `{$customFieldsTable}` table.");
86+
}
87+
} else {
88+
Schema::table($customFieldsTable, function (Blueprint $table) use ($columnsToAdd): void {
89+
if (in_array('custom_field_section_id', $columnsToAdd)) {
90+
$table->unsignedBigInteger('custom_field_section_id')->nullable()->after('id');
91+
}
92+
if (in_array('width', $columnsToAdd)) {
93+
$table->string('width')->nullable()->after('custom_field_section_id');
94+
}
95+
});
96+
foreach ($columnsToAdd as $column) {
97+
$command->info("Added `{$column}` column to `{$customFieldsTable}` table.");
98+
}
99+
}
100+
} else {
101+
$command->line("Columns `custom_field_section_id` and `width` already exist in `{$customFieldsTable}`. Skipping.");
102+
}
103+
}
104+
105+
private function removeDeletedAtColumns(Command $command, bool $isDryRun): void
106+
{
107+
$tablesWithDeletedAt = [
108+
config('custom-fields.table_names.custom_fields'),
109+
config('custom-fields.table_names.custom_field_options'),
110+
config('custom-fields.table_names.custom_field_values'),
111+
];
112+
113+
foreach ($tablesWithDeletedAt as $table) {
114+
if (Schema::hasColumn($table, 'deleted_at')) {
115+
if ($isDryRun) {
116+
$command->line("Column `deleted_at` would be removed from `{$table}` table.");
117+
} else {
118+
Schema::table($table, function (Blueprint $table): void {
119+
$table->dropSoftDeletes();
120+
});
121+
$command->info("Removed `deleted_at` column from `{$table}` table.");
122+
}
123+
} else {
124+
$command->line("Column `deleted_at` does not exist in `{$table}`. Skipping.");
125+
}
126+
}
127+
}
128+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace Relaticle\CustomFields\Commands\Upgrade;
4+
5+
use Closure;
6+
use Illuminate\Support\Facades\DB;
7+
use Relaticle\CustomFields\Commands\UpgradeCommand;
8+
use Relaticle\CustomFields\Enums\CustomFieldSectionType;
9+
use Relaticle\CustomFields\Enums\CustomFieldWidth;
10+
use Relaticle\CustomFields\Models\CustomField;
11+
use Relaticle\CustomFields\Models\CustomFieldSection;
12+
13+
class UpdateExistingData
14+
{
15+
public function handle(UpgradeCommand $command, Closure $next): mixed
16+
{
17+
$isDryRun = $command->isDryRun();
18+
19+
$command->info('--- Updating existing data...');
20+
$command->newLine();
21+
22+
DB::transaction(function () use ($command, $isDryRun): void {
23+
$entityTypes = CustomField::query()
24+
->whereNull('custom_field_section_id')
25+
->pluck('entity_type');
26+
27+
if ($entityTypes->isEmpty()) {
28+
$command->info('No custom fields found that require updating.');
29+
return;
30+
}
31+
32+
$command->info('Updating custom fields for the following entity types:');
33+
$command->line($entityTypes->implode(', '));
34+
$command->newLine();
35+
36+
$progressBar = $command->output->createProgressBar($entityTypes->count());
37+
$progressBar->start();
38+
39+
foreach ($entityTypes as $entityType) {
40+
if ($isDryRun) {
41+
$command->line("A new section would be created for entity type `{$entityType}`.");
42+
} else {
43+
$section = CustomFieldSection::create([
44+
'entity_type' => $entityType,
45+
'name' => __('custom-fields::custom-fields.section.default.new_section'),
46+
'code' => 'new_section',
47+
'type' => CustomFieldSectionType::HEADLESS,
48+
]);
49+
50+
CustomField::whereNull('custom_field_section_id')
51+
->where('entity_type', $entityType)
52+
->update([
53+
'custom_field_section_id' => $section->id,
54+
'width' => CustomFieldWidth::_100,
55+
]);
56+
57+
$command->line("Custom fields for entity type `{$entityType}` have been updated.");
58+
}
59+
$progressBar->advance();
60+
}
61+
62+
$progressBar->finish();
63+
$command->newLine(2);
64+
$command->info('Existing data update step completed.');
65+
});
66+
67+
return $next($command);
68+
}
69+
}

src/Commands/UpgradeCommand.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Relaticle\CustomFields\Commands;
6+
7+
use Illuminate\Console\Command;
8+
use Illuminate\Pipeline\Pipeline;
9+
use Throwable;
10+
use Relaticle\CustomFields\Commands\Upgrade\UpdateDatabaseSchema;
11+
use Relaticle\CustomFields\Commands\Upgrade\UpdateExistingData;
12+
13+
class UpgradeCommand extends Command
14+
{
15+
protected $signature = 'custom-fields:upgrade {--dry-run : Simulate the upgrade without making any changes}';
16+
protected $description = 'Upgrade the Custom Fields Filament Plugin to version 1.0';
17+
18+
public function handle(): int
19+
{
20+
$this->info('Welcome to the Custom Fields Upgrade Command!');
21+
$this->info('This command will upgrade the Custom Fields Filament Plugin to version 1.0.');
22+
$this->newLine();
23+
24+
if ($this->isDryRun()) {
25+
$this->warn('Running in Dry Run mode. No changes will be made.');
26+
}
27+
28+
if (!$this->confirm('Do you wish to continue?', true)) {
29+
$this->info('Upgrade cancelled by the user.');
30+
return self::SUCCESS;
31+
}
32+
33+
$this->newLine();
34+
35+
try {
36+
app(Pipeline::class)
37+
->send($this)
38+
->through([
39+
UpdateDatabaseSchema::class,
40+
UpdateExistingData::class,
41+
])
42+
->thenReturn();
43+
44+
$this->info('Upgrade completed successfully.');
45+
return self::SUCCESS;
46+
} catch (Throwable $e) {
47+
$this->error('An error occurred during the upgrade process:');
48+
$this->error($e->getMessage());
49+
50+
\Log::error('Custom Fields Upgrade Error:', [
51+
'message' => $e->getMessage(),
52+
'trace' => $e->getTraceAsString(),
53+
]);
54+
55+
return self::FAILURE;
56+
}
57+
}
58+
59+
public function isDryRun(): bool
60+
{
61+
return $this->option('dry-run');
62+
}
63+
}

0 commit comments

Comments
 (0)