Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions src/Commands/Upgrade/UpdateDatabaseSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

namespace Relaticle\CustomFields\Commands\Upgrade;

use Closure;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Relaticle\CustomFields\Commands\UpgradeCommand;
use Relaticle\CustomFields\Support\Utils;
use Illuminate\Console\Command;

class UpdateDatabaseSchema
{
public function handle(UpgradeCommand $command, Closure $next): mixed
{
$isDryRun = $command->isDryRun();

$command->info('--- Updating database schema...');
$command->newLine();

// Logic to update database schema
$this->createCustomFieldSectionsTable($command, $isDryRun);
$this->updateCustomFieldsTable($command, $isDryRun);
$this->removeDeletedAtColumns($command, $isDryRun);

$command->newLine();
$command->info('Database schema update step completed.');
$command->newLine();

return $next($command);
}

private function createCustomFieldSectionsTable(Command $command, bool $isDryRun): void
{
$sectionsTable = config('custom-fields.table_names.custom_field_sections', 'custom_field_sections');

if (!Schema::hasTable($sectionsTable)) {
if ($isDryRun) {
$command->line("Table `{$sectionsTable}` would be created.");
} else {
Schema::create($sectionsTable, function (Blueprint $table): void {
$table->id();
if (Utils::isTenantEnabled()) {
$table->foreignId(config('custom-fields.column_names.tenant_foreign_key'))->nullable()->index();
}
$table->string('code');
$table->string('name');
$table->string('type');
$table->string('entity_type');
$table->unsignedBigInteger('sort_order')->nullable();
$table->string('description')->nullable();
$table->boolean('active')->default(true);
$table->boolean('system_defined')->default(false);

$uniqueColumns = ['entity_type', 'code'];
if (Utils::isTenantEnabled()) {
$uniqueColumns[] = config('custom-fields.column_names.tenant_foreign_key');
}
$table->unique($uniqueColumns);

$table->timestamps();
});
$command->info("Table `{$sectionsTable}` created successfully.");
}
} else {
$command->line("Table `{$sectionsTable}` already exists. Skipping creation.");
}
}

private function updateCustomFieldsTable(Command $command, bool $isDryRun): void
{
$customFieldsTable = config('custom-fields.table_names.custom_fields');

$columnsToAdd = [];
if (!Schema::hasColumn($customFieldsTable, 'custom_field_section_id')) {
$columnsToAdd[] = 'custom_field_section_id';
}
if (!Schema::hasColumn($customFieldsTable, 'width')) {
$columnsToAdd[] = 'width';
}

if (!empty($columnsToAdd)) {
if ($isDryRun) {
foreach ($columnsToAdd as $column) {
$command->line("Column `{$column}` would be added to `{$customFieldsTable}` table.");
}
} else {
Schema::table($customFieldsTable, function (Blueprint $table) use ($columnsToAdd): void {
if (in_array('custom_field_section_id', $columnsToAdd)) {
$table->unsignedBigInteger('custom_field_section_id')->nullable()->after('id');
}
if (in_array('width', $columnsToAdd)) {
$table->string('width')->nullable()->after('custom_field_section_id');
}
});
foreach ($columnsToAdd as $column) {
$command->info("Added `{$column}` column to `{$customFieldsTable}` table.");
}
}
} else {
$command->line("Columns `custom_field_section_id` and `width` already exist in `{$customFieldsTable}`. Skipping.");
}
}

private function removeDeletedAtColumns(Command $command, bool $isDryRun): void
{
$tablesWithDeletedAt = [
config('custom-fields.table_names.custom_fields'),
config('custom-fields.table_names.custom_field_options'),
config('custom-fields.table_names.custom_field_values'),
];

foreach ($tablesWithDeletedAt as $table) {
if (Schema::hasColumn($table, 'deleted_at')) {
if ($isDryRun) {
$command->line("Column `deleted_at` would be removed from `{$table}` table.");
} else {
Schema::table($table, function (Blueprint $table): void {
$table->dropSoftDeletes();
});
$command->info("Removed `deleted_at` column from `{$table}` table.");
}
} else {
$command->line("Column `deleted_at` does not exist in `{$table}`. Skipping.");
}
}
}
}
69 changes: 69 additions & 0 deletions src/Commands/Upgrade/UpdateExistingData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Relaticle\CustomFields\Commands\Upgrade;

use Closure;
use Illuminate\Support\Facades\DB;
use Relaticle\CustomFields\Commands\UpgradeCommand;
use Relaticle\CustomFields\Enums\CustomFieldSectionType;
use Relaticle\CustomFields\Enums\CustomFieldWidth;
use Relaticle\CustomFields\Models\CustomField;
use Relaticle\CustomFields\Models\CustomFieldSection;

class UpdateExistingData
{
public function handle(UpgradeCommand $command, Closure $next): mixed
{
$isDryRun = $command->isDryRun();

$command->info('--- Updating existing data...');
$command->newLine();

DB::transaction(function () use ($command, $isDryRun): void {
$entityTypes = CustomField::query()
->whereNull('custom_field_section_id')
->pluck('entity_type');

if ($entityTypes->isEmpty()) {
$command->info('No custom fields found that require updating.');
return;
}

$command->info('Updating custom fields for the following entity types:');
$command->line($entityTypes->implode(', '));
$command->newLine();

$progressBar = $command->output->createProgressBar($entityTypes->count());
$progressBar->start();

foreach ($entityTypes as $entityType) {
if ($isDryRun) {
$command->line("A new section would be created for entity type `{$entityType}`.");
} else {
$section = CustomFieldSection::create([
'entity_type' => $entityType,
'name' => __('custom-fields::custom-fields.section.default.new_section'),
'code' => 'new_section',
'type' => CustomFieldSectionType::HEADLESS,
]);

CustomField::whereNull('custom_field_section_id')
->where('entity_type', $entityType)
->update([
'custom_field_section_id' => $section->id,
'width' => CustomFieldWidth::_100,
]);

$command->line("Custom fields for entity type `{$entityType}` have been updated.");
}
$progressBar->advance();
}

$progressBar->finish();
$command->newLine(2);
$command->info('Existing data update step completed.');
});

return $next($command);
}
}
63 changes: 63 additions & 0 deletions src/Commands/UpgradeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

declare(strict_types=1);

namespace Relaticle\CustomFields\Commands;

use Illuminate\Console\Command;
use Illuminate\Pipeline\Pipeline;
use Throwable;
use Relaticle\CustomFields\Commands\Upgrade\UpdateDatabaseSchema;
use Relaticle\CustomFields\Commands\Upgrade\UpdateExistingData;

class UpgradeCommand extends Command
{
protected $signature = 'custom-fields:upgrade {--dry-run : Simulate the upgrade without making any changes}';
protected $description = 'Upgrade the Custom Fields Filament Plugin to version 1.0';

public function handle(): int
{
$this->info('Welcome to the Custom Fields Upgrade Command!');
$this->info('This command will upgrade the Custom Fields Filament Plugin to version 1.0.');
$this->newLine();

if ($this->isDryRun()) {
$this->warn('Running in Dry Run mode. No changes will be made.');
}

if (!$this->confirm('Do you wish to continue?', true)) {
$this->info('Upgrade cancelled by the user.');
return self::SUCCESS;
}

$this->newLine();

try {
app(Pipeline::class)
->send($this)
->through([
UpdateDatabaseSchema::class,
UpdateExistingData::class,
])
->thenReturn();

$this->info('Upgrade completed successfully.');
return self::SUCCESS;
} catch (Throwable $e) {
$this->error('An error occurred during the upgrade process:');
$this->error($e->getMessage());

\Log::error('Custom Fields Upgrade Error:', [
'message' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);

return self::FAILURE;
}
}

public function isDryRun(): bool
{
return $this->option('dry-run');
}
}
Loading