where(function ($query): void { $query->where('expires_at', '<', now()) ->orWhereRaw('max_downloads IS NOT NULL AND download_count >= max_downloads'); }) ->get(); foreach ($expiredShares as $share) { $shareService->deleteShare($share); } $this->info("Cleaned up {$expiredShares->count()} expired share(s)."); // A page that stopped sending chunks: closed, crashed or left behind. $abandonedUploads = Share::query() ->whereNull('completed_at') ->where('updated_at', '<', now()->subHours(self::ABANDONED_AFTER_HOURS)) ->get(); foreach ($abandonedUploads as $share) { $shareService->deleteShare($share); } $this->info("Cleaned up {$abandonedUploads->count()} abandoned upload(s)."); $this->info('Cleaned up '.$this->deleteOldTemporaryUploads().' temporary upload file(s).'); return self::SUCCESS; } /** * Delete Livewire's temporary uploads past the same age: the admin logo's, and the unencrypted * copies uploads left there before files were encrypted in the browser. */ private function deleteOldTemporaryUploads(): int { if (FileUploadConfiguration::isUsingS3()) { return 0; } $storage = FileUploadConfiguration::storage(); $cutoff = now()->subHours(self::ABANDONED_AFTER_HOURS)->getTimestamp(); $deleted = 0; foreach ($storage->allFiles(FileUploadConfiguration::path()) as $path) { if ($storage->exists($path) && $storage->lastModified($path) < $cutoff) { $storage->delete($path); $deleted++; } } return $deleted; } }