platform user_id → local user id */ private array $userMap = []; /** @var array platform account id → local account id */ private array $accountMap = []; /** @var array platform node id → local node id */ private array $nodeMap = []; public function handle(): int { $commit = (bool) $this->option('commit'); if (! $commit) { $this->warn('DRY RUN — no changes will be written. Re-run with --commit to apply.'); } $path = $this->argument('file'); if (! is_file($path)) { $this->error("File not found: {$path}"); return self::FAILURE; } $payload = json_decode((string) file_get_contents($path), true); if (! is_array($payload)) { $this->error('Invalid JSON export file.'); return self::FAILURE; } $apply = function (callable $callback) use ($commit): void { if ($commit) { DB::transaction($callback); } else { $callback(); } }; $apply(function () use ($payload, $commit): void { foreach ($payload['hosting_nodes'] ?? [] as $row) { $this->importNode($row, $commit); } foreach ($payload['hosting_accounts'] ?? [] as $row) { $this->importAccount($row, $commit); } foreach ($payload['customer_hosting_orders'] ?? [] as $row) { $this->importCustomerOrder($row, $commit); } foreach ($payload['hosting_orders'] ?? [] as $row) { $this->importLegacyOrder($row, $commit); } foreach ($payload['hosting_account_members'] ?? [] as $row) { $this->importMember($row, $commit); } foreach ($payload['hosting_billing_invoices'] ?? [] as $row) { $this->importInvoice($row, $commit); } foreach ($payload['hosting_plan_changes'] ?? [] as $row) { $this->importPlanChange($row, $commit); } }); $this->info(($commit ? 'Imported' : 'Would import').' '.count($this->accountMap).' hosting account(s).'); return self::SUCCESS; } /** @param array $row */ private function importNode(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); unset($row['id'], $row['primary_hosting_node_id']); if ($commit) { $node = HostingNode::updateOrCreate(['hostname' => $row['hostname']], $row); $this->nodeMap[$platformId] = $node->id; } else { $this->nodeMap[$platformId] = $platformId; $this->line(" node {$platformId} → {$row['hostname']}"); } } /** @param array $row */ private function importAccount(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); $owner = $this->resolveUser( (string) ($row['owner_public_id'] ?? ''), (string) ($row['owner_email'] ?? ''), ); if (! $owner) { $this->warn("Skipping account #{$platformId}: no owner public_id"); return; } unset($row['id'], $row['owner_public_id'], $row['owner_email']); $row['user_id'] = $owner->id; $row['platform_id'] = $platformId; $this->mapProductId($row); $platformNodeId = (int) ($row['hosting_node_id'] ?? 0); if ($platformNodeId && isset($this->nodeMap[$platformNodeId])) { $row['hosting_node_id'] = $this->nodeMap[$platformNodeId]; } if ($commit) { $account = HostingAccount::updateOrCreate(['platform_id' => $platformId], $row); $this->accountMap[$platformId] = $account->id; } else { $this->accountMap[$platformId] = $platformId; $this->line(" account {$platformId} → user {$owner->email}"); } } /** @param array $row */ private function importCustomerOrder(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); $owner = $this->resolveUser((string) ($row['owner_public_id'] ?? '')); if (! $owner) { return; } unset($row['id'], $row['owner_public_id'], $row['owner_email']); $row['user_id'] = $owner->id; $row['platform_id'] = $platformId; $this->mapProductId($row); if ($commit) { CustomerHostingOrder::updateOrCreate(['platform_id' => $platformId], $row); } } /** @param array $row */ private function importLegacyOrder(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); $owner = $this->resolveUser((string) ($row['owner_public_id'] ?? '')); if (! $owner) { return; } unset($row['id'], $row['owner_public_id'], $row['owner_email']); $row['user_id'] = $owner->id; $row['platform_id'] = $platformId; if ($commit) { HostingOrder::updateOrCreate(['platform_id' => $platformId], $row); } } /** @param array $row */ private function importMember(array $row, bool $commit): void { $member = $this->resolveUser((string) ($row['member_public_id'] ?? '')); $platformAccountId = (int) ($row['hosting_account_id'] ?? 0); $localAccountId = $this->accountMap[$platformAccountId] ?? null; if (! $member || ! $localAccountId) { return; } unset($row['id'], $row['owner_public_id'], $row['member_public_id']); $row['user_id'] = $member->id; $row['hosting_account_id'] = $localAccountId; if (! empty($row['invited_by_user_id']) && ! User::query()->whereKey($row['invited_by_user_id'])->exists()) { $row['invited_by_user_id'] = null; } if ($commit) { HostingAccountMember::updateOrCreate( ['hosting_account_id' => $localAccountId, 'user_id' => $member->id], $row ); } } /** @param array $row */ private function importInvoice(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); $owner = $this->resolveUser((string) ($row['owner_public_id'] ?? '')); $platformAccountId = (int) ($row['hosting_account_id'] ?? 0); $localAccountId = $this->accountMap[$platformAccountId] ?? null; if (! $owner || ! $localAccountId) { return; } unset($row['id'], $row['owner_public_id'], $row['owner_email']); $row['user_id'] = $owner->id; $row['hosting_account_id'] = $localAccountId; $row['platform_id'] = $platformId; if ($commit) { HostingBillingInvoice::updateOrCreate(['platform_id' => $platformId], $row); } } /** @param array $row */ private function importPlanChange(array $row, bool $commit): void { $platformId = (int) ($row['id'] ?? 0); $owner = $this->resolveUser((string) ($row['owner_public_id'] ?? '')); $platformAccountId = (int) ($row['hosting_account_id'] ?? 0); $localAccountId = $this->accountMap[$platformAccountId] ?? null; if (! $owner || ! $localAccountId) { return; } unset($row['id'], $row['owner_public_id'], $row['owner_email']); $row['user_id'] = $owner->id; $row['hosting_account_id'] = $localAccountId; $row['platform_id'] = $platformId; if ($commit) { HostingPlanChange::updateOrCreate(['platform_id' => $platformId], $row); } } private function resolveUser(string $publicId, string $email = '', string $name = ''): ?User { if ($publicId === '') { return null; } $user = User::query()->where('public_id', $publicId)->first(); if ($user || $email === '') { return $user; } return User::query()->create([ 'public_id' => $publicId, 'email' => $email, 'name' => $name !== '' ? $name : $email, ]); } /** @param array $row */ private function mapProductId(array &$row): void { $slug = (string) ($row['hosting_product_slug'] ?? ''); unset($row['hosting_product_slug']); if ($slug === '') { return; } $product = HostingProduct::query()->where('slug', $slug)->first(); if ($product) { $row['hosting_product_id'] = $product->id; } } }