<?php
 declare(strict_types=1); namespace SpomkyLabs\Pki\X509\Certificate\Extension\CertificatePolicy; use ArrayIterator; use Countable; use IteratorAggregate; use LogicException; use SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence; use SpomkyLabs\Pki\ASN1\Type\Primitive\ObjectIdentifier; use SpomkyLabs\Pki\ASN1\Type\UnspecifiedType; use function count; final class PolicyInformation implements Countable, IteratorAggregate { final public const OID_ANY_POLICY = '2.5.29.32.0'; private array $qualifiers; private function __construct( private readonly string $oid, PolicyQualifierInfo ...$qualifiers ) { $this->qualifiers = []; foreach ($qualifiers as $qualifier) { $this->qualifiers[$qualifier->oid()] = $qualifier; } } public static function create(string $oid, PolicyQualifierInfo ...$qualifiers): self { return new self($oid, ...$qualifiers); } public static function fromASN1(Sequence $seq): self { $oid = $seq->at(0) ->asObjectIdentifier() ->oid(); $qualifiers = []; if (count($seq) > 1) { $qualifiers = array_map( static fn (UnspecifiedType $el) => PolicyQualifierInfo::fromASN1($el->asSequence()), $seq->at(1) ->asSequence() ->elements() ); } return self::create($oid, ...$qualifiers); } public function oid(): string { return $this->oid; } public function isAnyPolicy(): bool { return $this->oid === self::OID_ANY_POLICY; } public function qualifiers(): array { return array_values($this->qualifiers); } public function has(string $oid): bool { return isset($this->qualifiers[$oid]); } public function get(string $oid): PolicyQualifierInfo { if (! $this->has($oid)) { throw new LogicException("No {$oid} qualifier."); } return $this->qualifiers[$oid]; } public function hasCPSQualifier(): bool { return $this->has(PolicyQualifierInfo::OID_CPS); } public function CPSQualifier(): CPSQualifier { if (! $this->hasCPSQualifier()) { throw new LogicException('CPS qualifier not set.'); } return $this->get(PolicyQualifierInfo::OID_CPS); } public function hasUserNoticeQualifier(): bool { return $this->has(PolicyQualifierInfo::OID_UNOTICE); } public function userNoticeQualifier(): UserNoticeQualifier { if (! $this->hasUserNoticeQualifier()) { throw new LogicException('User notice qualifier not set.'); } return $this->get(PolicyQualifierInfo::OID_UNOTICE); } public function toASN1(): Sequence { $elements = [ObjectIdentifier::create($this->oid)]; if (count($this->qualifiers) !== 0) { $qualifiers = array_map( static fn (PolicyQualifierInfo $pqi) => $pqi->toASN1(), array_values($this->qualifiers) ); $elements[] = Sequence::create(...$qualifiers); } return Sequence::create(...$elements); } public function count(): int { return count($this->qualifiers); } public function getIterator(): ArrayIterator { return new ArrayIterator($this->qualifiers); } } 