Skip to content

Commit

Permalink
Add tagging to messages
Browse files Browse the repository at this point in the history
Signed-off-by: Anna Larch <anna@nextcloud.com>
  • Loading branch information
miaulalala committed Mar 4, 2021
1 parent 42ebb92 commit e9066e9
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 0 deletions.
10 changes: 10 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@
'url' => '/api/messages/{id}/flags',
'verb' => 'PUT'
],
[
'name' => 'messages#setTag',
'url' => '/api/messages/{id}/tags/{tagId}',
'verb' => 'PUT'
],
[
'name' => 'messages#removeTag',
'url' => '/api/messages/{id}/tags/{tagId}',
'verb' => 'DELETE'
],
[
'name' => 'messages#move',
'url' => '/api/messages/{id}/move',
Expand Down
64 changes: 64 additions & 0 deletions lib/Controller/MessagesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
use OCP\IL10N;
use OCP\IRequest;
use OCP\IURLGenerator;
use PDO;
use Psr\Log\LoggerInterface;
use function array_map;

Expand Down Expand Up @@ -649,6 +650,69 @@ public function setFlags(int $id, array $flags): JSONResponse {
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
*
* @param int $id
* @param array $flags
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
public function setTag(int $id, int $tagId): JSONResponse {
try {
$message = $this->mailManager->getMessage($this->currentUserId, $id);
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
$qb = $this->db->getQueryBuilder();
$qb->select()
->from('mail_tags')
->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($this->currentUserId)));
$qb->execute();
// fetch the label entry
$column = $qb->fetch(PDO::FETCH_ASSOC);
$qb->closeCursor();

if( $column === false ) {
throw new DoesNotExistException( 'Tag does not exist' );
}

$this->mailManager->tagMessage($account, $mailbox->getName(), $message->getUid(), $tag, 'true');
// add tagging logic here
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
*
* @param int $id
* @param array $flags
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
public function removeTag(int $id, int $tagId): JSONResponse {
try {
$message = $this->mailManager->getMessage($this->currentUserId, $id);
$mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
$account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse([], Http::STATUS_FORBIDDEN);
}
// add tagging logic here
return new JSONResponse();
}

/**
* @NoAdminRequired
* @TrapError
Expand Down
90 changes: 90 additions & 0 deletions lib/Migration/Version1100Date20210304143008.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php

declare(strict_types=1);

namespace OCA\Mail\Migration;

use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

/**
* Auto-generated migration step: Please modify to your needs!
*/
class Version1100Date20210304143008 extends SimpleMigrationStep {

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
$schema = $schemaClosure();

// @link https://github.com/nextcloud/mail/issues/4466
// $messageTable = $schema->getTable('mail_messages');
// $messageTable->addIndex(['thread_root_id'], 'mail_msgs_thread_root_id_index');

// @link https://github.com/nextcloud/mail/issues/25
if (!$schema->hasTable('mail_tags')) {
$tagsTable = $schema->createTable('mail_tags');
$tagsTable->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
'length' => 4,
]);
$tagsTable->addColumn('user_id', 'string', [
'notnull' => true,
'length' => 64,
]);
$tagsTable->addColumn('imap_label', 'string', [
'notnull' => true,
'length' => 64,
]);
$tagsTable->addColumn('display_name', 'string', [
'notnull' => true,
'length' => 128,
]);
// hex code plus transparency = #ffffffab
$tagsTable->addColumn('color', 'string', [
'notnull' => false,
'length' => 9,
]);
$tagsTable->setPrimaryKey(['id']);
}

if (!$schema->hasTable('mail_message_tags')) {
$tagsMessageTable = $schema->createTable('mail_message_tags');
$tagsMessageTable->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
'length' => 4,
]);
$tagsMessageTable->addColumn('imap_message_id', 'string', [
'notnull' => true,
'length' => 1023,
]);
$tagsMessageTable->addColumn('tag_id', 'integer', [
'notnull' => true,
'length' => 4,
]);
$tagsMessageTable->setPrimaryKey(['id']);
}
return $schema;

}

/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
*/
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
// add default labels here?
// if server doesn't support IMAP PERFLAGS move all flags tagged as important to tags table here
// reset cache
// rewrite $important tag for each message after cache has been resynced
}
}
37 changes: 37 additions & 0 deletions lib/Service/MailManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,43 @@ public function flagMessage(Account $account, string $mailbox, int $uid, string
);
}

public function tagMessage(Account $account, string $mailbox, int $uid, array $tag, bool $value): void {
$client = $this->imapClientFactory->getClient($account);
try {
$mb = $this->mailboxMapper->find($account, $mailbox);
} catch (DoesNotExistException $e) {
throw new ClientException("Mailbox $mailbox does not exist", 0, $e);
}

if( $this->isPermflagsEnabled( $account, $mailbox ) === true ) {
try {
if ($value === true) {
// imap keywords and flags work the same way
$this->imapMessageMapper->addFlag($client, $mb, $uid, $tag['imap_label']);
} else {
$this->imapMessageMapper->removeFlag($client, $mb, $uid, $tag['imap_label']);
}
} catch (Horde_Imap_Client_Exception $e) {
throw new ServiceException(
"Could not set message keyword on IMAP: " . $e->getMessage(),
(int) $e->getCode(),
$e
);
}
}

$this->eventDispatcher->dispatch(
MessageFlaggedEvent::class,
new MessageFlaggedEvent(
$account,
$mb,
$uid,
$tag['imap_label'],
$value
)
);
}

/**
* @param Account $account
*
Expand Down

0 comments on commit e9066e9

Please sign in to comment.