query_runner->execute( $this->query_runner->prepare( 'UPDATE ' . $this->tables->links() . ' SET check_after = 0 WHERE outcome = %s', Outcome::Listed->value ) ); } public function listed_total(): int { return $this->listed_count_where( self::EVERY_LINK ); } public function recheck_unconfirmed(): void { $this->query_runner->execute( $this->query_runner->prepare( 'UPDATE ' . $this->tables->links() . ' SET check_after = 0 WHERE outcome = %s AND ', Outcome::Listed->value ) . $this->unconfirmed_condition() ); } public function settled_since( int $started_at ): int { return $this->listed_count_where( 'checked_at >= %d AND NOT ' . $this->unconfirmed_condition(), $started_at ); } public function unfinished_total( int $started_at, int $now ): int { return $this->listed_count_where( '( ( check_after <= %d AND ( checked_at IS NULL OR checked_at < %d ) ) OR ' . $this->unconfirmed_condition() . ' )', $now, $started_at ); } private function unconfirmed_condition(): string { $reasons = array(); foreach ( Reason::cases() as $reason ) { if ( $reason->is_confirmed_by_repeating() ) { $reasons[] = $reason->value; } } $placeholders = array_fill( 0, count( $reasons ), '%s' ); return $this->query_runner->prepare( '( verdict = %s AND reason IS NOT NULL AND reason IN (' . implode( ', ', $placeholders ) . ') )', Verdict::Retrying->value, ...$reasons ); } private function listed_count_where( string $condition, int ...$values ): int { $count = $this->query_runner->value( $this->query_runner->prepare( 'SELECT COUNT(*) FROM ' . $this->tables->links() . ' WHERE outcome = %s AND ' . $condition, Outcome::Listed->value, ...$values ) ); return (int) $count; } }