pdo = $pdo; } public function findById(int $id): ?ScanJob { $stmt = $this->pdo->prepare('SELECT * FROM scan_jobs WHERE id = :id'); $stmt->execute(['id' => $id]); $row = $stmt->fetch(); return $row ? ScanJob::fromArray($row) : null; } public function findPending(): array { $stmt = $this->pdo->prepare('SELECT * FROM scan_jobs WHERE status = :status ORDER BY created_at ASC'); $stmt->execute(['status' => 'pending']); $results = []; while ($row = $stmt->fetch()) { $results[] = ScanJob::fromArray($row); } return $results; } public function findRecent(int $limit = 10): array { $stmt = $this->pdo->prepare('SELECT * FROM scan_jobs ORDER BY created_at DESC LIMIT :limit'); $stmt->bindValue('limit', $limit, PDO::PARAM_INT); $stmt->execute(); $results = []; while ($row = $stmt->fetch()) { $results[] = ScanJob::fromArray($row); } return $results; } public function findActive(): array { $statuses = ['pending', 'running', 'paused']; $placeholders = implode(',', array_fill(0, count($statuses), '?')); $stmt = $this->pdo->prepare("SELECT * FROM scan_jobs WHERE status IN ({$placeholders}) ORDER BY created_at ASC"); $stmt->execute($statuses); $results = []; while ($row = $stmt->fetch()) { $results[] = ScanJob::fromArray($row); } return $results; } public function findRunning(): array { $stmt = $this->pdo->prepare('SELECT * FROM scan_jobs WHERE status = :status ORDER BY started_at ASC'); $stmt->execute(['status' => 'running']); $results = []; while ($row = $stmt->fetch()) { $results[] = ScanJob::fromArray($row); } return $results; } public function updateStatus(int $id, string $status): void { $finishedAt = in_array($status, ['done', 'failed', 'cancelled'], true) ? (new \DateTimeImmutable())->format('Y-m-d H:i:s') : null; $stmt = $this->pdo->prepare( 'UPDATE scan_jobs SET status = :status, finished_at = :finished_at WHERE id = :id' ); $stmt->execute([ 'id' => $id, 'status' => $status, 'finished_at' => $finishedAt, ]); } public function save(ScanJob $job): void { $now = (new \DateTimeImmutable())->format('Y-m-d H:i:s'); if ($job->id === null) { $stmt = $this->pdo->prepare( 'INSERT INTO scan_jobs (type, status, network_range_id, device_id, created_by, created_at) VALUES (:type, :status, :network_range_id, :device_id, :created_by, :created_at)' ); $stmt->execute([ 'type' => $job->type, 'status' => $job->status, 'network_range_id' => $job->networkRangeId, 'device_id' => $job->deviceId, 'created_by' => $job->createdBy, 'created_at' => $now, ]); $job->id = (int)$this->pdo->lastInsertId(); } else { $stmt = $this->pdo->prepare( 'UPDATE scan_jobs SET type = :type, status = :status, network_range_id = :network_range_id, device_id = :device_id, started_at = :started_at, finished_at = :finished_at, error_message = :error_message, result_json = :result_json WHERE id = :id' ); $stmt->execute([ 'id' => $job->id, 'type' => $job->type, 'status' => $job->status, 'network_range_id' => $job->networkRangeId, 'device_id' => $job->deviceId, 'started_at' => $job->startedAt?->format('Y-m-d H:i:s'), 'finished_at' => $job->finishedAt?->format('Y-m-d H:i:s'), 'error_message' => $job->errorMessage, 'result_json' => $job->resultJson, ]); } } }