$layout * @param string[] $semantic_manifest */ public function __construct( private readonly int $id, private readonly string $uuid, private readonly string $template_key, private readonly int $version, private readonly string $origin, private readonly array $layout, private readonly string $template_html, private readonly string $template_css, private readonly array $semantic_manifest, private readonly string $content_hash, private readonly string $status, private readonly ?int $effective_from, private readonly ?int $effective_until, private readonly int $created_at, private readonly ?int $published_at ) { if ( '' === trim( $template_key ) || $version <= 0 ) { throw new \InvalidArgumentException( 'Template version identity is invalid.' ); } if ( 64 !== strlen( $content_hash ) || 1 !== preg_match( '/^[a-f0-9]{64}$/', $content_hash ) ) { throw new \InvalidArgumentException( 'Template content hash must be a lowercase SHA-256 digest.' ); } } public function id(): int { return $this->id; } public function uuid(): string { return $this->uuid; } public function template_key(): string { return $this->template_key; } public function version(): int { return $this->version; } public function origin(): string { return $this->origin; } public function layout(): array { return $this->layout; } public function template_html(): string { return $this->template_html; } public function template_css(): string { return $this->template_css; } public function semantic_manifest(): array { return $this->semantic_manifest; } public function content_hash(): string { return $this->content_hash; } public function status(): string { return $this->status; } public function effective_from(): ?int { return $this->effective_from; } public function effective_until(): ?int { return $this->effective_until; } public function created_at(): int { return $this->created_at; } public function published_at(): ?int { return $this->published_at; } public function is_effective_at( int $timestamp ): bool { return 'PUBLISHED' === strtoupper( $this->status ) && ( null === $this->effective_from || $timestamp >= $this->effective_from ) && ( null === $this->effective_until || $timestamp <= $this->effective_until ); } }