option('limit') ?? 0)); $fromId = max(0, (int) ($this->option('from-id') ?? 0)); $status = trim((string) ($this->option('status') ?? 'pending')); $force = (bool) $this->option('force'); $types = $this->selectedTypes(); $counts = [ 'rescanned' => 0, 'updated' => 0, 'auto_hidden' => 0, 'missing_source' => 0, ]; $query = ContentModerationFinding::query()->orderBy('id'); if ($status !== '') { $query->where('status', $status); } if ($fromId > 0) { $query->where('id', '>=', $fromId); } if ($types !== []) { $query->whereIn('content_type', array_map(static fn (ModerationContentType $type): string => $type->value, $types)); } if (! $force) { $query->where('status', ModerationStatus::Pending->value); } if ($limit > 0) { $query->limit($limit); } $query->chunkById(100, function ($findings) use (&$counts): bool { foreach ($findings as $finding) { $counts['rescanned']++; $rescanned = $this->processing->rescanFinding($finding, $this->sources); if ($rescanned === null) { $counts['missing_source']++; continue; } $counts['updated']++; if ($rescanned->is_auto_hidden) { $counts['auto_hidden']++; } $this->actionLogs->log( $rescanned, 'finding', $rescanned->id, 'rescan', null, null, $rescanned->status->value, null, null, 'Finding rescanned with the latest moderation rules.', ['scanner_version' => $rescanned->scanner_version], ); } return true; }, 'id'); $this->table(['Metric', 'Count'], [ ['Rescanned', $counts['rescanned']], ['Updated', $counts['updated']], ['Auto-hidden', $counts['auto_hidden']], ['Missing source', $counts['missing_source']], ]); $this->info('Content moderation rescan complete.'); return self::SUCCESS; } /** * @return array */ private function selectedTypes(): array { $raw = trim((string) ($this->option('only') ?? '')); if ($raw === '') { return []; } $selected = \collect(explode(',', $raw)) ->map(static fn (string $value): string => trim(strtolower($value))) ->filter() ->values(); $types = []; if ($selected->contains('comments')) { $types[] = ModerationContentType::ArtworkComment; } if ($selected->contains('descriptions')) { $types[] = ModerationContentType::ArtworkDescription; } if ($selected->contains('titles') || $selected->contains('artwork_titles')) { $types[] = ModerationContentType::ArtworkTitle; } if ($selected->contains('bios') || $selected->contains('user_bios')) { $types[] = ModerationContentType::UserBio; } if ($selected->contains('profile-links') || $selected->contains('profile_links')) { $types[] = ModerationContentType::UserProfileLink; } if ($selected->contains('collections') || $selected->contains('collection_titles')) { $types[] = ModerationContentType::CollectionTitle; $types[] = ModerationContentType::CollectionDescription; } if ($selected->contains('stories') || $selected->contains('story_titles')) { $types[] = ModerationContentType::StoryTitle; $types[] = ModerationContentType::StoryContent; } if ($selected->contains('cards') || $selected->contains('card_titles')) { $types[] = ModerationContentType::CardTitle; $types[] = ModerationContentType::CardText; } return $types; } }