Skip to content

Commit cd9e48c

Browse files
committed
feat: add command to migrate email field values to array format
1 parent 7aba8d1 commit cd9e48c

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Relaticle\CustomFields\Console\Commands;
6+
7+
use Illuminate\Console\Command;
8+
use Illuminate\Support\Facades\DB;
9+
10+
/**
11+
* Migrates email field values from string_value to json_value format.
12+
*
13+
* This command is needed after the EmailFieldType was changed from STRING
14+
* data type to MULTI_CHOICE, which stores values in json_value as an array.
15+
*/
16+
class MigrateEmailFieldValuesCommand extends Command
17+
{
18+
protected $signature = 'custom-fields:migrate-email-values
19+
{--dry-run : Show what would be migrated without making changes}
20+
{--force : Run without confirmation in production}';
21+
22+
protected $description = 'Migrate email field values from string_value to json_value array format';
23+
24+
public function handle(): int
25+
{
26+
$isDryRun = $this->option('dry-run');
27+
28+
if (app()->isProduction() && ! $isDryRun && ! $this->option('force')) {
29+
if (! $this->confirm('You are running in production. Are you sure you want to continue?')) {
30+
$this->info('Migration cancelled.');
31+
32+
return self::SUCCESS;
33+
}
34+
}
35+
36+
$fieldTable = config('custom-fields.database.table_names.custom_fields');
37+
$valueTable = config('custom-fields.database.table_names.custom_field_values');
38+
39+
// Find all email type custom fields
40+
$emailFields = DB::table($fieldTable)
41+
->where('type', 'email')
42+
->pluck('id');
43+
44+
if ($emailFields->isEmpty()) {
45+
$this->info('No email fields found. Nothing to migrate.');
46+
47+
return self::SUCCESS;
48+
}
49+
50+
$this->info(sprintf('Found %d email field(s).', $emailFields->count()));
51+
52+
// Find values that need migration (have string_value but no json_value)
53+
$valuesToMigrate = DB::table($valueTable)
54+
->whereIn('custom_field_id', $emailFields)
55+
->whereNotNull('string_value')
56+
->where('string_value', '!=', '')
57+
->where(function ($query) {
58+
$query->whereNull('json_value')
59+
->orWhere('json_value', '=', '[]')
60+
->orWhere('json_value', '=', 'null');
61+
})
62+
->get();
63+
64+
if ($valuesToMigrate->isEmpty()) {
65+
$this->info('No email values need migration. All values are already in the correct format.');
66+
67+
return self::SUCCESS;
68+
}
69+
70+
$this->info(sprintf('Found %d email value(s) to migrate.', $valuesToMigrate->count()));
71+
72+
if ($isDryRun) {
73+
$this->warn('Dry run mode - no changes will be made.');
74+
$this->newLine();
75+
76+
$this->table(
77+
['ID', 'Entity Type', 'Entity ID', 'Current Value', 'New Format'],
78+
$valuesToMigrate->map(fn ($value) => [
79+
$value->id,
80+
$value->entity_type,
81+
$value->entity_id,
82+
$value->string_value,
83+
json_encode([$value->string_value]),
84+
])->toArray()
85+
);
86+
87+
return self::SUCCESS;
88+
}
89+
90+
$bar = $this->output->createProgressBar($valuesToMigrate->count());
91+
$bar->start();
92+
93+
$migrated = 0;
94+
$errors = 0;
95+
96+
foreach ($valuesToMigrate as $value) {
97+
try {
98+
DB::table($valueTable)
99+
->where('id', $value->id)
100+
->update([
101+
'json_value' => json_encode([$value->string_value]),
102+
'string_value' => null,
103+
]);
104+
105+
$migrated++;
106+
} catch (\Throwable $e) {
107+
$this->newLine();
108+
$this->error(sprintf('Failed to migrate value ID %d: %s', $value->id, $e->getMessage()));
109+
$errors++;
110+
}
111+
112+
$bar->advance();
113+
}
114+
115+
$bar->finish();
116+
$this->newLine(2);
117+
118+
$this->info(sprintf('Migration complete. Migrated: %d, Errors: %d', $migrated, $errors));
119+
120+
return $errors > 0 ? self::FAILURE : self::SUCCESS;
121+
}
122+
}

src/CustomFieldsServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Livewire\Livewire;
1616
use Relaticle\CustomFields\Console\Commands\MakeCustomFieldsMigrationCommand;
1717
use Relaticle\CustomFields\Console\Commands\MakeFieldTypeCommand;
18+
use Relaticle\CustomFields\Console\Commands\MigrateEmailFieldValuesCommand;
1819
use Relaticle\CustomFields\Contracts\CustomsFieldsMigrators;
1920
use Relaticle\CustomFields\Contracts\ValueResolvers;
2021
use Relaticle\CustomFields\Enums\CustomFieldsFeature;
@@ -168,6 +169,7 @@ private function getCommands(): array
168169
return [
169170
MakeCustomFieldsMigrationCommand::class,
170171
MakeFieldTypeCommand::class,
172+
MigrateEmailFieldValuesCommand::class,
171173
];
172174
}
173175

0 commit comments

Comments
 (0)