generated from Nodarx/template
refactor: use custom imap client
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
86
lib/Client/Protocol/CommandExecutor.php
Normal file
86
lib/Client/Protocol/CommandExecutor.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace KTXM\ProviderImap\Client\Protocol;
|
||||
|
||||
use Generator;
|
||||
use KTXM\ProviderImap\Client\Command\CommandInterface;
|
||||
use KTXM\ProviderImap\Client\ImapException;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\TaggedResponse;
|
||||
use KTXM\ProviderImap\Client\Protocol\Response\UntaggedResponse;
|
||||
use KTXM\ProviderImap\Client\SessionContext;
|
||||
use KTXM\ProviderImap\Client\SessionState;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
final class CommandExecutor
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ProtocolReader $reader,
|
||||
private readonly ProtocolWriter $writer,
|
||||
private readonly TagGenerator $tags = new TagGenerator(),
|
||||
private readonly ?LoggerInterface $logger = null,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @template TResult
|
||||
* @param CommandInterface<TResult> $command
|
||||
* @return TResult
|
||||
*/
|
||||
public function perform(CommandInterface $command, SessionContext $context): mixed
|
||||
{
|
||||
$this->assertState($command->allowedStates(), $context->state(), $command->name());
|
||||
|
||||
$this->logger?->debug('IMAP command execution started: {command} (state={state})', [
|
||||
'command' => $command->name(),
|
||||
'state' => $context->state()->value,
|
||||
]);
|
||||
|
||||
$tag = $this->tags->next();
|
||||
$frame = $command->encode($tag, $context);
|
||||
$this->writer->write($tag, $frame);
|
||||
|
||||
return $command->handle(new ResponseStream(function () use ($tag, $context): Generator {
|
||||
yield from $this->responsesUntilCompletion($tag, $context);
|
||||
}), $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<SessionState> $allowedStates
|
||||
*/
|
||||
private function assertState(array $allowedStates, SessionState $currentState, string $commandName): void
|
||||
{
|
||||
foreach ($allowedStates as $allowedState) {
|
||||
if ($allowedState === $currentState) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ImapException(sprintf(
|
||||
'Command %s is not allowed while session is in state %s.',
|
||||
$commandName,
|
||||
$currentState->value,
|
||||
));
|
||||
}
|
||||
|
||||
private function responsesUntilCompletion(string $tag, SessionContext $context): Generator
|
||||
{
|
||||
while (true) {
|
||||
$response = $this->reader->readResponse();
|
||||
|
||||
if ($response instanceof UntaggedResponse && $response->label() === 'CAPABILITY') {
|
||||
$context->replaceCapabilities(...$response->payloadTokens());
|
||||
}
|
||||
|
||||
yield $response;
|
||||
|
||||
if ($response instanceof TaggedResponse && $response->tag() === $tag) {
|
||||
$this->logger?->debug('IMAP command execution completed: tag={tag} status={status}', [
|
||||
'tag' => $tag,
|
||||
'status' => $response->status(),
|
||||
]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user