generated from Nodarx/template
118 lines
3.2 KiB
PHP
118 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KTXM\ProviderImap\Client\Command;
|
|
|
|
use KTXM\ProviderImap\Client\Command\Result\StatusResult;
|
|
use KTXM\ProviderImap\Client\ImapException;
|
|
use KTXM\ProviderImap\Client\Protocol\RequestFrame;
|
|
use KTXM\ProviderImap\Client\Protocol\Response\TaggedResponse;
|
|
use KTXM\ProviderImap\Client\Protocol\Response\UntaggedResponse;
|
|
use KTXM\ProviderImap\Client\Protocol\ResponseStream;
|
|
use KTXM\ProviderImap\Client\SessionContext;
|
|
use KTXM\ProviderImap\Client\SessionState;
|
|
|
|
/**
|
|
* @implements CommandInterface<StatusResult>
|
|
*/
|
|
final class StatusCommand implements CommandInterface
|
|
{
|
|
private readonly StatusResponseParser $statusResponseParser;
|
|
|
|
/**
|
|
* @param list<string> $items
|
|
*/
|
|
public function __construct(
|
|
private readonly string $mailbox,
|
|
private readonly array $items = ['MESSAGES', 'UNSEEN'],
|
|
?StatusResponseParser $statusResponseParser = null,
|
|
) {
|
|
$this->statusResponseParser = $statusResponseParser ?? new StatusResponseParser();
|
|
}
|
|
|
|
public function name(): string
|
|
{
|
|
return 'STATUS';
|
|
}
|
|
|
|
public function allowedStates(): array
|
|
{
|
|
return [
|
|
SessionState::Authenticated,
|
|
SessionState::Selected,
|
|
];
|
|
}
|
|
|
|
public function encode(string $tag, SessionContext $context): RequestFrame
|
|
{
|
|
unset($tag, $context);
|
|
|
|
return new RequestFrame(sprintf(
|
|
'STATUS %s (%s)',
|
|
$this->quote($this->mailbox),
|
|
implode(' ', $this->normalizeItems($this->items)),
|
|
));
|
|
}
|
|
|
|
public function handle(ResponseStream $responses, SessionContext $context): StatusResult
|
|
{
|
|
unset($context);
|
|
|
|
$items = [];
|
|
$mailbox = $this->mailbox;
|
|
|
|
foreach ($responses as $response) {
|
|
if ($response instanceof UntaggedResponse && $response->label() === 'STATUS') {
|
|
[$mailbox, $items] = $this->statusResponseParser->parse($response->payload());
|
|
continue;
|
|
}
|
|
|
|
if ($response instanceof TaggedResponse) {
|
|
if (!$response->isOk()) {
|
|
throw new ImapException('STATUS failed: ' . $response->text());
|
|
}
|
|
|
|
return new StatusResult($mailbox, $items);
|
|
}
|
|
}
|
|
|
|
throw new ImapException('STATUS did not receive a tagged completion response.');
|
|
}
|
|
|
|
/**
|
|
* @param list<string> $items
|
|
* @return list<string>
|
|
*/
|
|
private function normalizeItems(array $items): array
|
|
{
|
|
$normalized = [];
|
|
|
|
foreach ($items as $item) {
|
|
$item = strtoupper(trim($item));
|
|
if ($item === '') {
|
|
continue;
|
|
}
|
|
|
|
if (!preg_match('/^[A-Z0-9.-]+$/', $item)) {
|
|
throw new ImapException('Invalid STATUS item: ' . $item);
|
|
}
|
|
|
|
if (in_array($item, $normalized, true)) {
|
|
continue;
|
|
}
|
|
|
|
$normalized[] = $item;
|
|
}
|
|
|
|
if ($normalized === []) {
|
|
throw new ImapException('STATUS requires at least one data item.');
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
private function quote(string $value): string
|
|
{
|
|
return '"' . addcslashes($value, "\\\"") . '"';
|
|
}
|
|
} |