option('scheduled') && ! $this->isCleanupEnabled()) { $this->info('고아 첨부 자동 정리가 꺼져 있어 실행하지 않았습니다. (upload.orphan_cleanup_enabled = false)'); return Command::SUCCESS; } $days = $this->resolveRetentionDays(); if ($days < 1) { $this->info('고아 첨부 보존기간이 1일 미만이어서 정리를 수행하지 않았습니다.'); return Command::SUCCESS; } $limit = max(1, (int) $this->option('limit')); $isDryRun = (bool) $this->option('dry-run'); $result = $this->attachmentService->pruneOrphans($days, $limit, $isDryRun); if ($isDryRun) { $this->info("[DRY RUN] 보존기간({$days}일) 경과 고아 첨부: {$result['scanned']}건"); return Command::SUCCESS; } $this->info(sprintf( '보존기간(%d일) 경과 고아 첨부 %d건 중 %d건을 삭제했습니다. (실패 %d건)', $days, $result['scanned'], $result['deleted'], $result['failed'], )); Log::info('PruneOrphanAttachmentsCommand: 고아 첨부 정리 완료', [ 'days' => $days, 'limit' => $limit, ] + $result); return Command::SUCCESS; } /** * 자동 정리 토글을 false 폴백으로 조회합니다. * * @return bool 자동 정리 활성 여부 */ private function isCleanupEnabled(): bool { return (bool) g7_core_settings('upload.orphan_cleanup_enabled', false); } /** * 보존기간을 해석합니다 (옵션 > 환경설정 > 기본 30일). * * @return int 보존기간(일) */ private function resolveRetentionDays(): int { $option = $this->option('days'); if ($option !== null && $option !== '') { return (int) $option; } return (int) g7_core_settings('upload.orphan_retention_days', 30); } }