simedkom/app/Console/Commands/MigrateUserCommand.php

172 lines
5.1 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use App\Enums\NotifStyle;
use App\Enums\RoleEnum;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateUserCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:user';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate users from legacy database with optimized processing and detailed output';
/**
* Cache for existing user IDs and emails to prevent redundant queries.
*/
private array $existingUserIds = [];
private array $existingUserEmails = [];
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting optimized user migration...');
$legacyConn = DB::connection('mysql_second');
$query = $legacyConn->table('users')->whereNull('deleted_at');
$totalCount = $query->count();
if ($totalCount === 0) {
$this->warn('No users found in legacy database.');
return;
}
$this->info("Found {$totalCount} legacy user records.");
// Pre-cache existing data to speed up individual checks
$this->existingUserIds = User::pluck('id')->flip()->all();
$this->existingUserEmails = User::pluck('email')->flip()->all();
$query->orderBy('id')->chunk(50, function ($chunk) {
foreach ($chunk as $legacy) {
$this->processUser($legacy);
}
});
$this->newLine();
$this->info('User migration completed successfully!');
}
/**
* Process a single legacy user record.
*/
private function processUser($legacy): void
{
$this->output->write("<info>[#{$legacy->id}]</info> Processing: <comment>".Str::limit($legacy->name, 40).'</comment>... ');
// Check for duplicates by ID or Email
if (isset($this->existingUserIds[$legacy->id]) || isset($this->existingUserEmails[$legacy->email])) {
$this->output->writeln('<info>SKIP (Already Exists)</info>');
return;
}
try {
$username = $this->generateUniqueUsername($legacy->name, $legacy->email);
$id = DB::table('users')->insertGetId([
'id' => $legacy->id,
'name' => Str::limit($legacy->name, 100),
'email' => $legacy->email,
'username' => $username,
'password' => $legacy->password,
'is_active' => $legacy->status == '2'
? IsActive::INACTIVE->value
: IsActive::ACTIVE->value,
'email_verified_at' => now(),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
]);
$user = User::find($id);
if ($user) {
// Assign Role
$roleName = $this->mapRole($legacy->role);
if ($roleName) {
$user->syncRoles([$roleName]);
}
// Initialize User Settings if missing
if (! $user->settings()->exists()) {
$user->settings()->create([
'notif_style' => NotifStyle::FORMAL,
'primary_color' => 'blue',
'font' => 'Inter',
'content_width' => 'full',
'border_radius' => 'lg',
'top_navigation' => false,
]);
}
$this->output->writeln('<info>DONE</info>');
} else {
$this->output->writeln('<error>FAILED TO RETRIEVE</error>');
}
} catch (\Exception $e) {
$this->output->writeln('<error>FAILED: '.$e->getMessage().'</error>');
}
}
/**
* Generate a unique username based on name or email.
*/
private function generateUniqueUsername($name, $email): string
{
$base = Str::limit(Str::slug($name, ''), 10, '');
if (empty($base)) {
$base = Str::limit(explode('@', $email)[0], 10, '');
}
$username = $base;
$counter = 1;
while (User::where('username', $username)->exists()) {
$suffix = (string) $counter;
$maxBaseLength = 10 - strlen($suffix);
$username = substr($base, 0, $maxBaseLength).$suffix;
$counter++;
if ($counter > 999) {
break;
}
}
return $username;
}
/**
* Map legacy role IDs to RoleEnum.
*/
private function mapRole($legacyRole): ?string
{
return match ((int) $legacyRole) {
1 => RoleEnum::ADMINISTRATOR->value,
2 => RoleEnum::ADMIN_MONITORING->value,
3 => RoleEnum::PERUSAHAAN->value,
4 => RoleEnum::ADMIN_KONTEN->value,
5 => RoleEnum::ADMIN_KEUANGAN->value,
default => null,
};
}
}