setTable('selfserve_config_versions'); } public function getObjectProperties(): void { $this->department_id = new object_property($this->table, $this->id, 'department_id', 'int', false); $this->status = new object_property($this->table, $this->id, 'status', 'string', false); $this->version_number = new object_property($this->table, $this->id, 'version_number', 'int', false); $this->config_json = new object_property($this->table, $this->id, 'config_json', 'json', false); $this->validation_result_json = new object_property($this->table, $this->id, 'validation_result_json', 'json', false); $this->source_version_id = new object_property($this->table, $this->id, 'source_version_id', 'int', false); $this->created_by = new object_property($this->table, $this->id, 'created_by', 'int', false); $this->published_at = new object_property($this->table, $this->id, 'published_at', 'datetime', false); $this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false); $this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false); $this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false); } public function objectChanged(): void { // No-op for now. } public function add( int $departmentId, string $status, int $versionNumber, array $config, ?array $validationResult = null, ?int $sourceVersionId = null, ?int $createdBy = null, ?string $publishedAt = null, ): self { $configJson = json_encode($config, JSON_UNESCAPED_UNICODE); if ($configJson === false) { throw new \RuntimeException('Failed to encode self-serve config JSON: ' . json_last_error_msg()); } $validationJson = null; if ($validationResult !== null) { $validationJson = json_encode($validationResult, JSON_UNESCAPED_UNICODE); if ($validationJson === false) { throw new \RuntimeException('Failed to encode self-serve validation JSON: ' . json_last_error_msg()); } } $this->id = $this->add_object([ 'department_id' => $departmentId, 'status' => $status, 'version_number' => $versionNumber, // Pass JSON as escaped strings to avoid SQL quoting issues inside generic add_object(). 'config_json' => $configJson, 'validation_result_json' => $validationJson, 'source_version_id' => $sourceVersionId, 'created_by' => $createdBy, 'published_at' => $publishedAt, ]); $this->getObjectProperties(); $this->objectChanged(); return $this; } public function selectLatestByDepartmentAndStatus(int $departmentId, string $status): self { $rows = $this->getFieldsWhere([ 'department_id' => $departmentId, 'status' => $status, 'deleted_at' => null, ], ['id']); if ($rows === []) { return $this; } usort($rows, static fn(array $a, array $b): int => (int)$b['id'] <=> (int)$a['id']); $this->select((int)$rows[0]['id']); return $this; } public function listByDepartment(int $departmentId): array { $rows = $this->getFieldsWhere([ 'department_id' => $departmentId, 'deleted_at' => null, ], ['id']); if ($rows === []) { return []; } usort($rows, static fn(array $a, array $b): int => (int)$b['id'] <=> (int)$a['id']); return array_map(function (array $row): array { return (new selfserve_config_versions_o())->select((int)$row['id'])->asArray(); }, $rows); } public function asArray(): array { return [ 'id' => (int)$this->id, 'department_id' => (int)$this->department_id->value(), 'status' => (string)$this->status->value(), 'version_number' => (int)$this->version_number->value(), 'config' => (array)($this->config_json->value() ?? []), 'validation_result' => (array)($this->validation_result_json->value() ?? []), 'source_version_id' => $this->source_version_id->value() === null ? null : (int)$this->source_version_id->value(), 'created_by' => $this->created_by->value() === null ? null : (int)$this->created_by->value(), 'published_at' => $this->published_at->value() === null ? null : (string)$this->published_at->value(), 'created_at' => (string)$this->created_at->value(), 'updated_at' => $this->updated_at->value() === null ? null : (string)$this->updated_at->value(), ]; } }