$options */ private function __construct( private readonly array $options, ) {} public static function none(): self { return new self([]); } public static function of(string ...$options): self { return new self(self::normalize($options)); } public static function subscribed(): self { return self::none()->withSubscribed(); } public static function remote(): self { return self::none()->withRemote(); } public static function specialUse(): self { return self::none()->withSpecialUse(); } public function withSubscribed(): self { return $this->with(self::SUBSCRIBED); } public function withRemote(): self { return $this->with(self::REMOTE); } public function withRecursiveMatch(): self { return $this->with(self::RECURSIVEMATCH); } public function withSpecialUse(): self { return $this->with(self::SPECIAL_USE); } /** * @return list */ public function toArray(): array { return $this->options; } public function toCommand(): ?string { if ($this->options === []) { return null; } return '(' . implode(' ', $this->options) . ')'; } private function with(string $option): self { return new self(self::normalize([ ...$this->options, $option, ])); } /** * @param list $options * @return list */ private static function normalize(array $options): array { $normalized = []; foreach ($options as $option) { $option = strtoupper(trim($option)); if ($option === '') { continue; } if (!in_array($option, [ self::SUBSCRIBED, self::REMOTE, self::RECURSIVEMATCH, self::SPECIAL_USE, ], true)) { throw new ImapException('Unsupported LIST selection option: ' . $option); } if (in_array($option, $normalized, true)) { continue; } $normalized[] = $option; } if (in_array(self::RECURSIVEMATCH, $normalized, true) && !in_array(self::SUBSCRIBED, $normalized, true)) { throw new ImapException('RECURSIVEMATCH requires SUBSCRIBED in LIST selection options.'); } return $normalized; } }