<?php
 declare(strict_types=1); namespace SpomkyLabs\Pki\X509\Certificate\Extension; use ArrayIterator; use Countable; use IteratorAggregate; use SpomkyLabs\Pki\ASN1\Element; use SpomkyLabs\Pki\ASN1\Type\Constructed\Sequence; use SpomkyLabs\Pki\ASN1\Type\UnspecifiedType; use SpomkyLabs\Pki\X509\Certificate\Extension\Target\Target; use SpomkyLabs\Pki\X509\Certificate\Extension\Target\Targets; use function count; final class TargetInformationExtension extends Extension implements Countable, IteratorAggregate { protected array $targets; private ?Targets $merged = null; private function __construct(bool $critical, Targets ...$targets) { parent::__construct(self::OID_TARGET_INFORMATION, $critical); $this->targets = $targets; } public function __clone() { $this->merged = null; } public static function create(bool $critical, Targets ...$targets): self { return new self($critical, ...$targets); } public static function fromTargets(Target ...$target): self { return self::create(true, Targets::create(...$target)); } public function targets(): Targets { if ($this->merged === null) { $a = []; foreach ($this->targets as $targets) { $a = array_merge($a, $targets->all()); } $this->merged = Targets::create(...$a); } return $this->merged; } public function names(): array { return $this->targets() ->nameTargets(); } public function groups(): array { return $this->targets() ->groupTargets(); } public function count(): int { return count($this->targets()); } public function getIterator(): ArrayIterator { return new ArrayIterator($this->targets()->all()); } protected static function fromDER(string $data, bool $critical): static { $targets = array_map( static fn (UnspecifiedType $el) => Targets::fromASN1($el->asSequence()), UnspecifiedType::fromDER($data)->asSequence()->elements() ); return self::create($critical, ...$targets); } protected function valueASN1(): Element { $elements = array_map(static fn (Targets $targets) => $targets->toASN1(), $this->targets); return Sequence::create(...$elements); } } 