data = $data; } public static function current(): ?self { $raw = get_option(WPH_OPT_SESSION); if (!is_array($raw) || empty($raw['id'])) return null; return new self($raw); } public static function start(int $technician_id): self { $data = [ 'id' => uniqid('wph_', true), 'started_at' => time(), 'finished_at' => null, 'technician_id'=> $technician_id, 'site_url' => get_site_url(), 'wp_version' => get_bloginfo('version'), 'php_version' => PHP_VERSION, 'steps' => [], // keyed by step id → ['status' => ..., 'notes' => ..., 'updated_at' => ...] ]; update_option(WPH_OPT_SESSION, $data, false); return new self($data); } public static function discard(): void { delete_option(WPH_OPT_SESSION); } public function id(): string { return (string) $this->data['id']; } public function started_at(): int { return (int) $this->data['started_at']; } public function finished_at(): ?int { return isset($this->data['finished_at']) ? (int) $this->data['finished_at'] : null; } public function is_finished(): bool { return $this->finished_at() !== null; } public function technician_id(): int { return (int) $this->data['technician_id']; } public function site_url(): string { return (string) ($this->data['site_url'] ?? get_site_url()); } public function wp_version(): string { return (string) ($this->data['wp_version'] ?? ''); } public function php_version(): string { return (string) ($this->data['php_version'] ?? ''); } public function data(): array { return $this->data; } public function step_state(string $step_id): array { return $this->data['steps'][$step_id] ?? [ 'status' => self::STATUS_NOT_STARTED, 'notes' => '', 'updated_at' => null, ]; } public function update_step(string $step_id, string $status, string $notes): void { if (!in_array($status, self::VALID_STATUSES, true)) { $status = self::STATUS_NOT_STARTED; } $this->data['steps'][$step_id] = [ 'status' => $status, 'notes' => $notes, 'updated_at' => time(), ]; update_option(WPH_OPT_SESSION, $this->data, false); } public function finish(): void { $this->data['finished_at'] = time(); update_option(WPH_OPT_SESSION, $this->data, false); } /** Store the result of running autocheck() on a step. */ public function set_autocheck(string $step_id, array $findings): void { $this->data['autocheck'][$step_id] = [ 'checked_at' => time(), 'findings' => $findings, ]; update_option(WPH_OPT_SESSION, $this->data, false); } /** Returns ['checked_at'=>int, 'findings'=>array] or null. */ public function get_autocheck(string $step_id): ?array { return $this->data['autocheck'][$step_id] ?? null; } public function progress(): array { $steps = WPH_Steps::instance()->all(); $total = count($steps); $done = 0; foreach ($steps as $step) { $st = $this->step_state($step->id()); if (in_array($st['status'], [self::STATUS_DONE, self::STATUS_SKIPPED, self::STATUS_NA], true)) { $done++; } } return ['done' => $done, 'total' => $total]; } }