Skip to content

Commit 317167e

Browse files
committed
WIP
1 parent 1c0fe56 commit 317167e

25 files changed

+286
-1164
lines changed

src/Connection/Connection.php

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use DirectoryTree\ImapEngine\Exceptions\ConnectionFailedException;
1010
use DirectoryTree\ImapEngine\Exceptions\ConnectionTimedOutException;
1111
use DirectoryTree\ImapEngine\Exceptions\RuntimeException;
12-
use DirectoryTree\ImapEngine\Imap;
1312
use DirectoryTree\ImapEngine\Support\Str;
1413

1514
abstract class Connection implements ConnectionInterface
@@ -229,7 +228,7 @@ public function getCryptoMethod(): int
229228
/**
230229
* Enable STARTTLS on the current connection.
231230
*/
232-
protected function enableStartTls(): void
231+
public function startTls(): void
233232
{
234233
$this->send('STARTTLS', tag: $tag);
235234

@@ -303,7 +302,7 @@ public function connect(string $host, ?int $port = null): void
303302
$this->setStreamTimeout($this->connectionTimeout);
304303

305304
if ($transport === 'starttls') {
306-
$this->enableStartTls();
305+
$this->startTls();
307306
}
308307
}
309308

@@ -320,6 +319,10 @@ protected function getTransport(): string
320319
*/
321320
public function nextReply(): Response
322321
{
322+
if (! $this->parser) {
323+
throw new RuntimeException('Connection must be opened before reading replies.');
324+
}
325+
323326
if (! $reply = $this->parser->next()) {
324327
$meta = $this->meta();
325328

@@ -340,30 +343,27 @@ public function nextReply(): Response
340343
/**
341344
* Send an IMAP command.
342345
*/
343-
public function send(string $name, array $tokens = [], ?string &$tag = null): void
346+
public function send(string $name, array|string $tokens = [], ?string &$tag = null): void
344347
{
345-
$command = new ImapCommand($name, $tokens);
346-
347348
if (! $tag) {
348349
$this->sequence++;
349350
$tag = 'TAG'.$this->sequence;
350351
}
351352

352-
$command->setTag($tag);
353-
354-
$result = new Result;
353+
$command = new ImapCommand($name, $tag, (array) $tokens);
355354

356-
$this->setResult($result);
357-
358-
$result->addCommand($command);
355+
// After every command, we'll overwrite any previous result
356+
// with the new command and its responses, so that we can
357+
// easily access the commands responses for assertion.
358+
$this->setResult(new Result($command));
359359

360360
foreach ($command->compile() as $line) {
361361
$this->write($line);
362362
}
363363
}
364364

365365
/**
366-
* Write data to the stream.
366+
* Write data to the connected stream.
367367
*/
368368
protected function write(string $data): void
369369
{
@@ -383,37 +383,18 @@ protected function write(string $data): void
383383
*/
384384
public function fetch(array|string $items, array|int $from, mixed $to = null, ImapFetchIdentifier $identifier = ImapFetchIdentifier::Uid): ResponseCollection
385385
{
386-
if (is_array($from) && count($from) > 1) {
387-
$set = implode(',', $from);
388-
} elseif (is_array($from) && count($from) === 1) {
389-
$set = $from[0].':'.$from[0];
390-
} elseif (is_null($to)) {
391-
$set = $from.':'.$from;
392-
} elseif ($to == INF) {
393-
$set = $from.':*';
394-
} else {
395-
$set = $from.':'.(int) $to;
396-
}
397-
398-
$items = (array) $items;
399-
400386
$prefix = ($identifier === ImapFetchIdentifier::Uid) ? 'UID' : '';
401387

402-
$this->send(trim($prefix.' FETCH'), [$set, $this->escapeList($items)], $tag);
388+
$this->send(trim($prefix.' FETCH'), [
389+
Str::set($from, $to),
390+
Str::list((array) $items),
391+
], $tag);
403392

404393
$this->assertTaggedResponse($tag, fn () => new RuntimeException('Failed to fetch items'));
405394

406395
return $this->result->responses()->untagged();
407396
}
408397

409-
/**
410-
* Escape one or more literal strings.
411-
*/
412-
protected function escapeString(array|string ...$string): array|string
413-
{
414-
return Str::literal(...$string);
415-
}
416-
417398
/**
418399
* Escape a list of literals.
419400
*/

src/Connection/FakeConnection.php

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace DirectoryTree\ImapEngine\Connection;
44

55
use DirectoryTree\ImapEngine\Connection\Responses\UntaggedResponse;
6-
use DirectoryTree\ImapEngine\Imap;
76
use RuntimeException;
87

98
/**
@@ -121,47 +120,47 @@ public function capability(): UntaggedResponse
121120
/**
122121
* {@inheritDoc}
123122
*/
124-
public function selectFolder(string $folder = 'INBOX'): ResponseCollection
123+
public function select(string $folder = 'INBOX'): ResponseCollection
125124
{
126125
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
127126
}
128127

129128
/**
130129
* {@inheritDoc}
131130
*/
132-
public function examineFolder(string $folder = 'INBOX'): ResponseCollection
131+
public function examine(string $folder = 'INBOX'): ResponseCollection
133132
{
134133
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
135134
}
136135

137136
/**
138137
* {@inheritDoc}
139138
*/
140-
public function folderStatus(string $folder = 'INBOX', array $arguments = ['MESSAGES', 'UNSEEN', 'RECENT', 'UIDNEXT', 'UIDVALIDITY']): ResponseCollection
139+
public function status(string $folder = 'INBOX', array $arguments = ['MESSAGES', 'UNSEEN', 'RECENT', 'UIDNEXT', 'UIDVALIDITY']): ResponseCollection
141140
{
142141
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
143142
}
144143

145144
/**
146145
* {@inheritDoc}
147146
*/
148-
public function uids(int|array $msgns): ResponseCollection
147+
public function uid(int|array $msgns): ResponseCollection
149148
{
150149
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
151150
}
152151

153152
/**
154153
* {@inheritDoc}
155154
*/
156-
public function contents(array|int $ids): ResponseCollection
155+
public function text(array|int $ids): ResponseCollection
157156
{
158157
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
159158
}
160159

161160
/**
162161
* {@inheritDoc}
163162
*/
164-
public function headers(array|int $ids): ResponseCollection
163+
public function header(array|int $ids): ResponseCollection
165164
{
166165
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
167166
}
@@ -185,7 +184,7 @@ public function sizes(array|int $ids): ResponseCollection
185184
/**
186185
* {@inheritDoc}
187186
*/
188-
public function folders(string $reference = '', string $folder = '*'): ResponseCollection
187+
public function list(string $reference = '', string $folder = '*'): ResponseCollection
189188
{
190189
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
191190
}
@@ -201,15 +200,15 @@ public function store(array|string $flags, int $from, ?int $to = null, ?string $
201200
/**
202201
* {@inheritDoc}
203202
*/
204-
public function appendMessage(string $folder, string $message, ?array $flags = null, ?string $date = null): ResponseCollection
203+
public function append(string $folder, string $message, ?array $flags = null, ?string $date = null): ResponseCollection
205204
{
206205
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
207206
}
208207

209208
/**
210209
* {@inheritDoc}
211210
*/
212-
public function copyMessage(string $folder, $from, ?int $to = null): ResponseCollection
211+
public function copy(string $folder, $from, ?int $to = null): ResponseCollection
213212
{
214213
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
215214
}
@@ -225,7 +224,7 @@ public function copyManyMessages(array $messages, string $folder): ResponseColle
225224
/**
226225
* {@inheritDoc}
227226
*/
228-
public function moveMessage(string $folder, $from, ?int $to = null): ResponseCollection
227+
public function move(string $folder, $from, ?int $to = null): ResponseCollection
229228
{
230229
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
231230
}
@@ -249,39 +248,39 @@ public function id(?array $ids = null): ResponseCollection
249248
/**
250249
* {@inheritDoc}
251250
*/
252-
public function createFolder(string $folder): ResponseCollection
251+
public function create(string $folder): ResponseCollection
253252
{
254253
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
255254
}
256255

257256
/**
258257
* {@inheritDoc}
259258
*/
260-
public function renameFolder(string $oldPath, string $newPath): ResponseCollection
259+
public function rename(string $oldPath, string $newPath): ResponseCollection
261260
{
262261
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
263262
}
264263

265264
/**
266265
* {@inheritDoc}
267266
*/
268-
public function deleteFolder(string $folder): ResponseCollection
267+
public function delete(string $folder): ResponseCollection
269268
{
270269
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
271270
}
272271

273272
/**
274273
* {@inheritDoc}
275274
*/
276-
public function subscribeFolder(string $folder): ResponseCollection
275+
public function subscribe(string $folder): ResponseCollection
277276
{
278277
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
279278
}
280279

281280
/**
282281
* {@inheritDoc}
283282
*/
284-
public function unsubscribeFolder(string $folder): ResponseCollection
283+
public function unsubscribe(string $folder): ResponseCollection
285284
{
286285
return $this->getExpectationResponse(__FUNCTION__, func_get_args()) ?? ResponseCollection::make();
287286
}

src/Connection/ImapCommand.php

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,25 @@
22

33
namespace DirectoryTree\ImapEngine\Connection;
44

5-
class ImapCommand
6-
{
7-
/**
8-
* The IMAP command name.
9-
*/
10-
protected string $command;
11-
12-
/**
13-
* The IMAP command tokens.
14-
*/
15-
protected array $tokens;
16-
17-
/**
18-
* The IMAP command tag.
19-
*/
20-
protected ?string $tag = null;
5+
use Stringable;
216

7+
class ImapCommand implements Stringable
8+
{
229
/**
23-
* Constructor.
10+
* The compiled command lines.
2411
*
25-
* @param string $command The IMAP command name (e.g. 'LOGIN', 'FETCH', etc.)
26-
* @param array $tokens Any additional parameters for the command.
12+
* @var string[]
2713
*/
28-
public function __construct(string $command, array $tokens = [])
29-
{
30-
$this->command = $command;
31-
$this->tokens = $tokens;
32-
}
14+
protected ?array $compiled = null;
3315

3416
/**
35-
* Set the tag for this command.
36-
*/
37-
public function setTag(string $tag): self
38-
{
39-
$this->tag = $tag;
40-
41-
return $this;
42-
}
43-
44-
/**
45-
* Get the command tag.
17+
* Constructor.
4618
*/
47-
public function getTag(): ?string
48-
{
49-
return $this->tag;
50-
}
19+
public function __construct(
20+
protected string $tag,
21+
protected string $command,
22+
protected array $tokens = [],
23+
) {}
5124

5225
/**
5326
* Build the command lines for transmission.
@@ -60,6 +33,10 @@ public function getTag(): ?string
6033
*/
6134
public function compile(): array
6235
{
36+
if ($this->compiled) {
37+
return $this->compiled;
38+
}
39+
6340
$lines = [];
6441

6542
$base = trim(($this->tag ?? '').' '.$this->command);
@@ -82,4 +59,12 @@ public function compile(): array
8259

8360
return $lines;
8461
}
62+
63+
/**
64+
* Get the command as a string.
65+
*/
66+
public function __toString(): string
67+
{
68+
return implode("\r\n", $this->compile());
69+
}
8570
}

0 commit comments

Comments
 (0)