Skip to content

Commit d83254a

Browse files
committed
WIP
1 parent bb857c7 commit d83254a

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

src/Connection/ConnectionInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function search(array $params): UntaggedResponse;
6868
*
6969
* @see https://datatracker.ietf.org/doc/html/rfc2971.
7070
*/
71-
public function id(?array $ids = null): ResponseCollection;
71+
public function id(?array $ids = null): UntaggedResponse;
7272

7373
/**
7474
* Fetch message UIDs using the given message numbers.

src/Connection/ImapConnection.php

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public function copyManyMessages(array $messages, string $folder): ResponseColle
216216

217217
$tokens = [$set, $this->escapeString($folder)];
218218

219-
$this->send('UID COPY', $tokens, false);
219+
$this->send('UID COPY', $tokens);
220220
}
221221

222222
/**
@@ -226,7 +226,7 @@ public function moveMessage(string $folder, $from, ?int $to = null): ResponseCol
226226
{
227227
$set = $this->buildSet($from, $to);
228228

229-
return $this->send('UID MOVE', [$set, $this->escapeString($folder)], false);
229+
return $this->send('UID MOVE', [$set, $this->escapeString($folder)]);
230230
}
231231

232232
/**
@@ -238,37 +238,27 @@ public function moveManyMessages(array $messages, string $folder): ResponseColle
238238

239239
$tokens = [$set, $this->escapeString($folder)];
240240

241-
return $this->send('UID MOVE', $tokens, false);
241+
return $this->send('UID MOVE', $tokens);
242242
}
243243

244244
/**
245245
* {@inheritDoc}
246246
*/
247247
public function store(array|string $flags, int $from, ?int $to = null, ?string $mode = null, bool $silent = true, ?string $item = null): ResponseCollection
248248
{
249-
$flags = $this->escapeList(Arr::wrap($flags));
250-
251249
$set = $this->buildSet($from, $to);
252250

253-
$item = ($mode == '-' ? '-' : '+').(is_null($item) ? 'FLAGS' : $item).($silent ? '.SILENT' : '');
254-
255-
$response = $this->send('UID STORE', [$set, $item, $flags], ! $silent);
251+
$flags = $this->escapeList(Arr::wrap($flags));
256252

257-
if ($silent) {
258-
return $response;
259-
}
253+
$item = ($mode == '-' ? '-' : '+').(is_null($item) ? 'FLAGS' : $item).($silent ? '.SILENT' : '');
260254

261-
$result = [];
255+
$this->send('UID STORE', [$set, $item, $flags], tag: $tag);
262256

263-
foreach ($response->data() as $token) {
264-
if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
265-
continue;
266-
}
257+
$this->assertTaggedResponse($tag, fn () => new RuntimeException('Failed to store flags'));
267258

268-
$result[$token[0]] = $token[2][1];
269-
}
270-
271-
return $response->setResult($result);
259+
return $silent ? new ResponseCollection : $this->result->responses()->untagged()->filter(
260+
fn (UntaggedResponse $response) => $response->type()->is('FETCH')
261+
);
272262
}
273263

274264
/**
@@ -320,7 +310,7 @@ public function search(array $params): UntaggedResponse
320310

321311
$this->assertTaggedResponse($tag, fn () => new RuntimeException('Failed to search messages'));
322312

323-
return $this->result->responses()->untagged()->firstWhere(
313+
return $this->result->responses()->untagged()->firstOrFail(
324314
fn (UntaggedResponse $response) => $response->type()->is('SEARCH')
325315
);
326316
}
@@ -334,15 +324,15 @@ public function capability(): UntaggedResponse
334324

335325
$this->assertTaggedResponse($tag, fn () => new RuntimeException('Failed to fetch capabilities'));
336326

337-
return $this->result->responses()->untagged()->firstWhere(
327+
return $this->result->responses()->untagged()->firstOrFail(
338328
fn (UntaggedResponse $response) => $response->type()->is('CAPABILITY')
339329
);
340330
}
341331

342332
/**
343333
* {@inheritDoc}
344334
*/
345-
public function id(?array $ids = null): ResponseCollection
335+
public function id(?array $ids = null): UntaggedResponse
346336
{
347337
$token = 'NIL';
348338

@@ -356,7 +346,13 @@ public function id(?array $ids = null): ResponseCollection
356346
$token = rtrim($token).')';
357347
}
358348

359-
return $this->requestAndResponse('ID', [$token], false);
349+
$this->send('ID', [$token], tag: $tag);
350+
351+
$this->assertTaggedResponse($tag, fn () => new RuntimeException('Failed to send ID'));
352+
353+
return $this->result->responses()->untagged()->firstOrFail(
354+
fn (UntaggedResponse $response) => $response->type()->is('CAPABILITY')
355+
);
360356
}
361357

362358
/**

src/Connection/Tokens/Atom.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace DirectoryTree\ImapEngine\Connection\Tokens;
44

5+
/**
6+
* @see https://datatracker.ietf.org/doc/html/rfc9051#name-atom
7+
*/
58
class Atom extends Token
69
{
710
/**

src/MessageQuery.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ public function getQuery(): string
655655
*/
656656
protected function search(): Collection
657657
{
658+
// If no conditions are set, default to fetching all.
658659
if (empty($this->conditions)) {
659660
$this->all();
660661
}

tests/ImapParserTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,42 @@
149149
expect((string) $response5)->toBe('TAG2 OK FETCH completed');
150150
});
151151

152+
test('parses list response', function () {
153+
$stream = new FakeStream;
154+
$stream->open();
155+
156+
$stream->feed([
157+
'* LIST (\Marked \NoInferiors) "/" "inbox"',
158+
'* LIST () "/" "Fruit"',
159+
'* LIST () "/" "Fruit/Apple"',
160+
'* LIST () "/" "Fruit/Banana"',
161+
]);
162+
163+
$tokenizer = new ImapTokenizer($stream);
164+
$parser = new ImapParser($tokenizer);
165+
166+
$response1 = $parser->next();
167+
$response2 = $parser->next();
168+
$response3 = $parser->next();
169+
$response4 = $parser->next();
170+
171+
expect($response1)->toBeInstanceOf(UntaggedResponse::class);
172+
expect($response1->tokens())->toHaveCount(5);
173+
expect((string) $response1)->toBe('* LIST (\Marked \NoInferiors) "/" "inbox"');
174+
175+
expect($response2)->toBeInstanceOf(UntaggedResponse::class);
176+
expect($response2->tokens())->toHaveCount(5);
177+
expect((string) $response2)->toBe('* LIST () "/" "Fruit"');
178+
179+
expect($response3)->toBeInstanceOf(UntaggedResponse::class);
180+
expect($response3->tokens())->toHaveCount(5);
181+
expect((string) $response3)->toBe('* LIST () "/" "Fruit/Apple"');
182+
183+
expect($response4)->toBeInstanceOf(UntaggedResponse::class);
184+
expect($response4->tokens())->toHaveCount(5);
185+
expect((string) $response4)->toBe('* LIST () "/" "Fruit/Banana"');
186+
});
187+
152188
test('parses quota response', function () {
153189
$stream = new FakeStream;
154190
$stream->open();

0 commit comments

Comments
 (0)