option('list')) { return $this->listDeletedProfiles(); } // Get username argument $username = $this->argument('username'); // If no username provided, ask for it if (!$username) { $username = $this->ask('Enter the username of the profile to restore'); } if (!$username) { $this->error('Username is required.'); return 1; } // Search for the deleted profile $profile = $this->findDeletedProfile($username); if (!$profile) { $this->error("No deleted profile found with username: {$username}"); $this->info('Use --list option to see all restorable profiles.'); return 1; } // Display profile information $profileType = class_basename(get_class($profile)); $deletedAt = $profile->deleted_at; $gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30); $expiresAt = $deletedAt->copy()->addDays($gracePeriodDays); // Calculate remaining time more accurately if (now()->greaterThanOrEqualTo($expiresAt)) { $timeRemaining = 'EXPIRED'; } else { $daysRemaining = now()->diffInDays($expiresAt, false); if ($daysRemaining > 0) { $timeRemaining = $daysRemaining . ' day' . ($daysRemaining > 1 ? 's' : ''); } else { $hoursRemaining = now()->diffInHours($expiresAt, false); $timeRemaining = $hoursRemaining . ' hour' . ($hoursRemaining > 1 ? 's' : ''); } } $this->info("Profile found:"); $this->table( ['Field', 'Value'], [ ['Type', $profileType], ['Username', $profile->name], ['Full Name', $profile->full_name ?? 'N/A'], ['Email', $profile->email], ['Deleted At', $deletedAt->format('Y-m-d H:i:s')], ['Grace Period Expires', $expiresAt->format('Y-m-d H:i:s')], ['Days Remaining', $timeRemaining], ] ); // Confirm restoration if (!$this->confirm('Do you want to restore this profile?')) { $this->info('Restoration cancelled.'); return 0; } // Restore the profile $restoreAction = new RestoreProfile(); $result = $restoreAction->restore($profile); if ($result['status'] === 'success') { $this->info("✓ Profile '{$profile->name}' has been successfully restored!"); Log::info("Profile restored via artisan command", [ 'profile_type' => get_class($profile), 'profile_id' => $profile->id, 'profile_name' => $profile->name, 'restored_by' => 'CLI', ]); return 0; } else { $this->error("✗ Failed to restore profile: {$result['message']}"); return 1; } } /** * List all deleted profiles within grace period */ protected function listDeletedProfiles() { $gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30); $gracePeriodExpiry = now()->subDays($gracePeriodDays); $profileTypes = [ 'User' => User::class, 'Organization' => Organization::class, 'Bank' => Bank::class, 'Admin' => Admin::class, ]; // Filter by type if provided $typeFilter = $this->option('type'); if ($typeFilter) { $typeFilter = ucfirst(strtolower($typeFilter)); if (!isset($profileTypes[$typeFilter])) { $this->error("Invalid profile type. Valid types: user, organization, bank, admin"); return 1; } $profileTypes = [$typeFilter => $profileTypes[$typeFilter]]; } $allDeletedProfiles = []; foreach ($profileTypes as $typeName => $modelClass) { // Find profiles that are deleted, within grace period, and not anonymized $profiles = $modelClass::whereNotNull('deleted_at') ->where('deleted_at', '>', $gracePeriodExpiry) ->where('email', 'not like', 'removed-%@remove.ed') ->orderBy('deleted_at', 'desc') ->get(); foreach ($profiles as $profile) { $expiresAt = $profile->deleted_at->copy()->addDays($gracePeriodDays); // Calculate remaining time more accurately if (now()->greaterThanOrEqualTo($expiresAt)) { $timeRemaining = 'EXPIRED'; } else { $daysRemaining = now()->diffInDays($expiresAt, false); if ($daysRemaining > 0) { $timeRemaining = $daysRemaining . 'd'; } else { $hoursRemaining = now()->diffInHours($expiresAt, false); $timeRemaining = $hoursRemaining . 'h'; } } $allDeletedProfiles[] = [ 'Type' => $typeName, 'Username' => $profile->name, 'Full Name' => $profile->full_name ?? 'N/A', 'Email' => $profile->email, 'Deleted At' => $profile->deleted_at->format('Y-m-d H:i'), 'Expires At' => $expiresAt->format('Y-m-d H:i'), 'Time Left' => $timeRemaining, 'Comment' => $profile->comment ?? '', ]; } } if (empty($allDeletedProfiles)) { $this->info('No deleted profiles found within the grace period.'); return 0; } $this->info("Deleted profiles within {$gracePeriodDays}-day grace period:"); $this->table( ['Type', 'Username', 'Full Name', 'Email', 'Deleted At', 'Expires At', 'Time Left', 'Comment'], $allDeletedProfiles ); $this->info("\nTo restore a profile, run: php artisan profiles:restore {username}"); return 0; } /** * Find a deleted profile by username across all profile types */ protected function findDeletedProfile($username) { $gracePeriodDays = timebank_config('delete_profile.grace_period_days', 30); $gracePeriodExpiry = now()->subDays($gracePeriodDays); $profileTypes = [ User::class, Organization::class, Bank::class, Admin::class, ]; foreach ($profileTypes as $modelClass) { $profile = $modelClass::whereNotNull('deleted_at') ->where('deleted_at', '>', $gracePeriodExpiry) ->where('email', 'not like', 'removed-%@remove.ed') ->where('name', $username) ->first(); if ($profile) { return $profile; } } return null; } }