option('days'); $isDryRun = $this->option('dry-run'); $cutoff = now()->subDays($days); $drafts = PressRelease::withoutGlobalScopes() ->where('status', PressReleaseStatus::Draft->value) ->where('updated_at', '<', $cutoff); // Abgelehnt und nie veröffentlicht: nur Meldungen, an denen noch // Bilder hängen — sonst wäre der Lauf jede Woche derselbe Zähler. $rejected = PressRelease::withoutGlobalScopes() ->where('status', PressReleaseStatus::Rejected->value) ->whereNull('published_ever_at') ->where('updated_at', '<', $cutoff) ->whereHas('images'); $draftCount = $drafts->count(); $rejectedCount = $rejected->count(); if ($isDryRun) { $this->warn("[DRY-RUN] {$draftCount} Entwürfe würden archiviert, {$rejectedCount} abgelehnte Einreichungen würden bereinigt. Kein tatsächlicher Vorgang."); return self::SUCCESS; } // Bilder nie veröffentlichter Entwürfe werden mit dem Purge sofort // und vollständig gelöscht (Bildkennzeichnung E.3, Decision-Update E4). $remover = app(PressReleaseImageRemover::class); $imagesRemoved = $this->removeImages((clone $drafts)->whereNull('published_ever_at'), $remover) + $this->removeImages(clone $rejected, $remover); $drafts->update(['status' => PressReleaseStatus::Archived->value]); $this->info("PM-Entwürfe archiviert: {$draftCount} Einträge, abgelehnte Einreichungen bereinigt: {$rejectedCount}, Bilder gelöscht: {$imagesRemoved}."); return self::SUCCESS; } /** * @param Builder $query */ private function removeImages(Builder $query, PressReleaseImageRemover $remover): int { $removed = 0; $query->with('images')->chunkById(200, function ($pressReleases) use ($remover, &$removed): void { foreach ($pressReleases as $pressRelease) { foreach ($pressRelease->images as $image) { $remover->remove($image); $removed++; } } }); return $removed; } }