Skip to content

Commit

Permalink
Implement bulk-move (#306)
Browse files Browse the repository at this point in the history
Closes #305
  • Loading branch information
particleflux authored and Slamdunk committed Feb 28, 2018
1 parent f90d03f commit d892189
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 19 deletions.
72 changes: 58 additions & 14 deletions src/Mailbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use DateTimeInterface;
use Ddeboer\Imap\Exception\InvalidSearchCriteriaException;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageMoveException;
use Ddeboer\Imap\Search\ConditionInterface;
use Ddeboer\Imap\Search\LogicalOperator\All;

Expand Down Expand Up @@ -118,35 +120,27 @@ public function getStatus(int $flags = null): \stdClass
/**
* Bulk Set Flag for Messages.
*
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|string $numbers Message numbers
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|MessageIterator|string $numbers Message numbers
*
* @return bool
*/
public function setFlag(string $flag, $numbers): bool
{
if (\is_array($numbers)) {
$numbers = \implode(',', $numbers);
}

return \imap_setflag_full($this->resource->getStream(), (string) $numbers, $flag, \ST_UID);
return \imap_setflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
}

/**
* Bulk Clear Flag for Messages.
*
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|string $numbers Message numbers
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|MessageIterator|string $numbers Message numbers
*
* @return bool
*/
public function clearFlag(string $flag, $numbers): bool
{
if (\is_array($numbers)) {
$numbers = \implode(',', $numbers);
}

return \imap_clearflag_full($this->resource->getStream(), (string) $numbers, $flag, \ST_UID);
return \imap_clearflag_full($this->resource->getStream(), $this->prepareMessageIds($numbers), $flag, \ST_UID);
}

/**
Expand Down Expand Up @@ -247,4 +241,54 @@ public function getThread(): array

return false !== $tree ? $tree : [];
}

/**
* Bulk move messages.
*
* @param array|MessageIterator|string $numbers Message numbers
* @param MailboxInterface $mailbox Destination Mailbox to move the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageMoveException
*/
public function move($numbers, MailboxInterface $mailbox)
{
if (!\imap_mail_move($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
throw new MessageMoveException(\sprintf('Messages cannot be moved to "%s"', $mailbox->getName()));
}
}

/**
* Bulk copy messages.
*
* @param array|MessageIterator|string $numbers Message numbers
* @param MailboxInterface $mailbox Destination Mailbox to copy the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageCopyException
*/
public function copy($numbers, MailboxInterface $mailbox)
{
if (!\imap_mail_copy($this->resource->getStream(), $this->prepareMessageIds($numbers), $mailbox->getEncodedName(), \CP_UID)) {
throw new MessageCopyException(\sprintf('Messages cannot be copied to "%s"', $mailbox->getName()));
}
}

/**
* Prepare message ids for the use with bulk functions.
*
* @param array|MessageIterator|string $messageIds Message numbers
*
* @return string
*/
private function prepareMessageIds($messageIds): string
{
if ($messageIds instanceof MessageIterator) {
$messageIds = $messageIds->getArrayCopy();
}

if (\is_array($messageIds)) {
$messageIds = \implode(',', $messageIds);
}

return (string) $messageIds;
}
}
28 changes: 24 additions & 4 deletions src/MailboxInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ public function getStatus(int $flags = null): \stdClass;
/**
* Bulk Set Flag for Messages.
*
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|string $numbers Message numbers
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|MessageIterator|string $numbers Message numbers
*
* @return bool
*/
Expand All @@ -69,8 +69,8 @@ public function setFlag(string $flag, $numbers): bool;
/**
* Bulk Clear Flag for Messages.
*
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|string $numbers Message numbers
* @param string $flag \Seen, \Answered, \Flagged, \Deleted, and \Draft
* @param array|MessageIterator|string $numbers Message numbers
*
* @return bool
*/
Expand Down Expand Up @@ -118,4 +118,24 @@ public function addMessage(string $message, string $options = null, DateTimeInte
* @return array
*/
public function getThread(): array;

/**
* Bulk move messages.
*
* @param array|MessageIterator|string $numbers Message numbers
* @param MailboxInterface $mailbox Destination Mailbox to move the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageMoveException
*/
public function move($numbers, self $mailbox);

/**
* Bulk copy messages.
*
* @param array|MessageIterator|string $numbers Message numbers
* @param MailboxInterface $mailbox Destination Mailbox to copy the messages to
*
* @throws \Ddeboer\Imap\Exception\MessageCopyException
*/
public function copy($numbers, self $mailbox);
}
53 changes: 52 additions & 1 deletion tests/MailboxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
namespace Ddeboer\Imap\Tests;

use DateTimeImmutable;
use Ddeboer\Imap\Exception\MessageCopyException;
use Ddeboer\Imap\Exception\MessageDoesNotExistException;
use Ddeboer\Imap\Exception\MessageMoveException;
use Ddeboer\Imap\Exception\ReopenMailboxException;
use Ddeboer\Imap\Mailbox;
use Ddeboer\Imap\MailboxInterface;
use Ddeboer\Imap\MessageIterator;

/**
* @covers \Ddeboer\Imap\Exception\AbstractException
Expand All @@ -16,6 +19,7 @@
*/
final class MailboxTest extends AbstractTest
{
/** @var MailboxInterface */
protected $mailbox;

protected function setUp()
Expand Down Expand Up @@ -215,4 +219,51 @@ public function testAppendOptionalArguments()
$this->assertTrue($message->isSeen());
$this->assertSame(' 3-Jan-2012 09:30:03 +0000', $message->getHeaders()->get('maildate'));
}

public function testBulkMove()
{
$anotherMailbox = $this->createMailbox();

// Test move by id
$messages = [1, 2, 3];

$this->assertSame(0, $anotherMailbox->count());
$this->mailbox->move($messages, $anotherMailbox);
$this->getConnection()->expunge();

$this->assertSame(3, $anotherMailbox->count());
$this->assertSame(0, $this->mailbox->count());

// move back by iterator
/** @var MessageIterator $messages */
$messages = $anotherMailbox->getMessages();
$anotherMailbox->move($messages, $this->mailbox);
$this->getConnection()->expunge();

$this->assertSame(0, $anotherMailbox->count());
$this->assertSame(3, $this->mailbox->count());

// test failing bulk move - try to move to a non-existent mailbox
$this->getConnection()->deleteMailbox($anotherMailbox);
$this->expectException(MessageMoveException::class);
$this->mailbox->move($messages, $anotherMailbox);
}

public function testBulkCopy()
{
$anotherMailbox = $this->createMailbox();
$messages = [1, 2, 3];

$this->assertSame(0, $anotherMailbox->count());
$this->assertSame(3, $this->mailbox->count());
$this->mailbox->copy($messages, $anotherMailbox);

$this->assertSame(3, $anotherMailbox->count());
$this->assertSame(3, $this->mailbox->count());

// test failing bulk copy - try to move to a non-existent mailbox
$this->getConnection()->deleteMailbox($anotherMailbox);
$this->expectException(MessageCopyException::class);
$this->mailbox->copy($messages, $anotherMailbox);
}
}

0 comments on commit d892189

Please sign in to comment.