$items */ private function __construct( private readonly array $items, ) {} public static function default(): self { return (new self([])) ->withUid() ->withFlags() ->withInternalDate() ->withSize(); } public static function message(): self { return self::default() ->withHeaders() ->withEnvelope() ->withBodyStructure(); } public static function of(string ...$items): self { return new self(self::normalize($items)); } public function withUid(): self { return $this->with('UID'); } public function withFlags(): self { return $this->with('FLAGS'); } public function withInternalDate(): self { return $this->with('INTERNALDATE'); } public function withSize(): self { return $this->with('RFC822.SIZE'); } public function withHeaders(): self { return $this->with('BODY.PEEK[HEADER]'); } public function withHeader(string ...$fields): self { $fields = array_values(array_filter(array_map( static fn (string $field): string => strtoupper(trim($field)), $fields, ), static fn (string $field): bool => $field !== '')); if ($fields === []) { return $this; } return $this->with(sprintf('BODY.PEEK[HEADER.FIELDS (%s)]', implode(' ', $fields))); } public function withEnvelope(): self { return $this->with('ENVELOPE'); } public function withBodyStructure(): self { return $this->with('BODYSTRUCTURE'); } /** * @param int|null $limit Maximum number of octets to fetch (partial fetch `<0.limit>`), null for all */ public function withBodyText(?int $limit = null): self { if ($limit !== null && $limit > 0) { return $this->with(sprintf('BODY.PEEK[TEXT]<0.%d>', $limit)); } return $this->with('BODY.PEEK[TEXT]'); } public function withBody(): self { return $this->with('BODY.PEEK[]'); } public function withBodySection(string $section): self { $section = strtoupper(trim($section)); if ($section === '') { return $this; } return $this->with(sprintf('BODY.PEEK[%s]', $section)); } public function with(string $item): self { return new self(self::normalize([ ...$this->items, $item, ])); } /** * @return list */ public function toArray(): array { return $this->items; } public function toCommand(): string { return implode(' ', $this->items); } /** * @param list $items * @return list */ private static function normalize(array $items): array { $normalized = []; foreach ($items as $item) { $item = trim($item); if ($item === '' || in_array($item, $normalized, true)) { continue; } $normalized[] = $item; } if (!in_array('UID', $normalized, true)) { array_unshift($normalized, 'UID'); } return $normalized; } }