, main_hash:string} $incomingFiles * @return array */ public function assertCanCreateDraft(User $user, array $incomingFiles): array { $maxDrafts = max(1, (int) config('uploads.draft_quota.max_drafts_per_user', 10)); $maxStorageMb = max(1, (int) config('uploads.draft_quota.max_draft_storage_mb_per_user', 1024)); $maxStorageBytes = $maxStorageMb * 1024 * 1024; $policy = (string) config('uploads.draft_quota.duplicate_hash_policy', 'block'); $warnings = []; $draftCount = DB::table('uploads') ->where('user_id', (int) $user->id) ->where('status', 'draft') ->count(); if ($draftCount >= $maxDrafts) { throw DraftQuotaException::draftLimit(); } $currentDraftStorage = (int) DB::table('upload_files as uf') ->join('uploads as u', 'u.id', '=', 'uf.upload_id') ->where('u.user_id', (int) $user->id) ->where('u.status', 'draft') ->sum(DB::raw('COALESCE(uf.size, 0)')); $incomingSize = $this->incomingSizeBytes((array) ($incomingFiles['files'] ?? [])); if (($currentDraftStorage + $incomingSize) > $maxStorageBytes) { throw DraftQuotaException::storageLimit(); } $mainHash = strtolower(trim((string) ($incomingFiles['main_hash'] ?? ''))); if ($mainHash !== '' && $this->publishedMainHashExists($mainHash)) { if ($policy === 'warn') { $warnings[] = 'duplicate_hash'; } else { throw DraftQuotaException::duplicateUpload(); } } return $warnings; } /** * @param array $files */ private function incomingSizeBytes(array $files): int { $total = 0; foreach ($files as $file) { if (! $file instanceof UploadedFile) { continue; } $size = $file->getSize(); if (is_numeric($size)) { $total += (int) $size; } } return max(0, $total); } private function publishedMainHashExists(string $hash): bool { return DB::table('upload_files as uf') ->join('uploads as u', 'u.id', '=', 'uf.upload_id') ->where('uf.type', 'main') ->where('uf.hash', $hash) ->where('u.status', 'published') ->exists(); } }