tenant; if ($tenant) { $this->purgeTenantMedia($tenant); $this->scrubTenantData($tenant); } $this->scrubUser($user); }); } public function anonymizeTenantOnly(Tenant $tenant): void { DB::transaction(function () use ($tenant) { $this->purgeTenantMedia($tenant); $this->scrubTenantData($tenant); }); } protected function purgeTenantMedia(Tenant $tenant): void { EventMediaAsset::query() ->whereHas('event', fn ($query) => $query->where('tenant_id', $tenant->id)) ->chunkById(100, function ($assets) { foreach ($assets as $asset) { if ($asset->disk && $asset->path) { Storage::disk($asset->disk)->delete($asset->path); } $asset->delete(); } }); Photo::query() ->where(function ($query) use ($tenant) { $query->where('tenant_id', $tenant->id) ->orWhereHas('event', fn ($inner) => $inner->where('tenant_id', $tenant->id)); }) ->chunkById(200, function ($photos) { foreach ($photos as $photo) { $photo->delete(); } }); } protected function scrubTenantData(Tenant $tenant): void { $eventIds = Event::query() ->where('tenant_id', $tenant->id) ->pluck('id'); EventJoinToken::query()->whereIn('event_id', $eventIds)->delete(); EventMember::query()->where('tenant_id', $tenant->id)->delete(); Event::query() ->whereIn('id', $eventIds) ->chunkById(100, function ($events) { foreach ($events as $event) { $event->forceFill([ 'name' => ['de' => 'Anonymisiertes Event', 'en' => 'Anonymized Event'], 'description' => null, 'location' => null, 'slug' => 'anonymized-event-'.$event->id, 'status' => 'archived', 'photobooth_enabled' => false, 'photobooth_path' => null, ])->save(); } }); PackagePurchase::query() ->where('tenant_id', $tenant->id) ->update([ 'ip_address' => null, 'user_agent' => null, ]); CheckoutSession::query() ->where('tenant_id', $tenant->id) ->update([ 'tenant_id' => null, 'user_id' => null, 'provider_metadata' => [], ]); TenantPackage::query() ->where('tenant_id', $tenant->id) ->update(['active' => false]); $tenant->forceFill([ 'name' => 'Anonymisierter Tenant #'.$tenant->id, 'slug' => 'anonymized-tenant-'.$tenant->id, 'contact_name' => null, 'contact_email' => null, 'contact_phone' => null, 'email' => null, 'domain' => null, 'custom_domain' => null, 'user_id' => null, 'anonymized_at' => now(), 'pending_deletion_at' => null, 'deletion_warning_sent_at' => null, 'subscription_status' => 'deleted', 'is_active' => 0, 'is_suspended' => 1, ])->save(); } protected function scrubUser(User $user): void { $placeholderEmail = sprintf('deleted+%s@fotospiel.app', $user->id); $user->forceFill([ 'name' => 'Anonymisierter Benutzer', 'email' => $placeholderEmail, 'username' => null, 'first_name' => null, 'last_name' => null, 'address' => null, 'phone' => null, 'password' => Str::random(40), 'remember_token' => null, 'pending_purchase' => false, 'email_verified_at' => null, 'role' => 'user', ])->save(); } }