rows = $rows; $this->channel = $channel; $this->log = $log; } /** * Reads and stores the status of one listing. * * @param int $id Listing ID. * @return array|null The new row, or null when there is nothing to check or the marketplace could not be reached. */ public function poll( int $id ): ?array { $row = $this->rows->find( $id ); if ( null === $row || '' === (string) $row['remote_id'] ) { return null; } try { $outcome = $this->channel->status( (string) $row['remote_id'] ); $fields = $outcome->fields(); $reason = ''; if ( in_array( $outcome->state, array( ListingStatus::PENDING_REVIEW, ListingStatus::ERROR ), true ) && 'new' !== $outcome->remote_status ) { $reason = ErrorExplainer::for_channel( $this->channel )->explain_message( $this->channel->rejection_reason( (string) $row['remote_id'] ) ); } $fields['last_error'] = $reason; $fields['last_synced_at'] = gmdate( 'Y-m-d H:i:s' ); $this->rows->update( $id, $fields ); } catch ( ChannelException $e ) { $this->log->log( Logger::WARNING, 'status', sprintf( 'Status check of listing %d failed: %s', $id, $e->getMessage() ) ); return null; } return $this->rows->find( $id ); } /** * Polls every listing of this channel that is waiting to be accepted or paid. * * @return array{checked:int, failed:int} */ public function poll_waiting(): array { $stats = array( 'checked' => 0, 'failed' => 0, ); foreach ( $this->rows->all( array( 'status' => array( ListingStatus::PENDING_REVIEW, ListingStatus::LIMITED ), 'channel' => $this->channel->id(), ) ) as $row ) { if ( null === $this->poll( (int) $row['id'] ) ) { ++$stats['failed']; } else { ++$stats['checked']; } } return $stats; } }