mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-19 13:22:42 +01:00
Fully modularize mail commands
Summary: Ref T7199. Everyone can have a mail command! You can have a mail command! You can have a mail command! Mail commands for everyone! Test Plan: Used `bin/mail receive-test` to issue commands against files and pastes. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7199 Differential Revision: https://secure.phabricator.com/D12238
This commit is contained in:
parent
7c5f71b691
commit
c32fee0e48
6 changed files with 175 additions and 40 deletions
|
@ -1069,6 +1069,7 @@ phutil_register_library_map(array(
|
|||
'ManiphestUpdateConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestUpdateConduitAPIMethod.php',
|
||||
'ManiphestView' => 'applications/maniphest/view/ManiphestView.php',
|
||||
'MetaMTAConstants' => 'applications/metamta/constants/MetaMTAConstants.php',
|
||||
'MetaMTAEmailTransactionCommand' => 'applications/metamta/command/MetaMTAEmailTransactionCommand.php',
|
||||
'MetaMTAMailReceivedGarbageCollector' => 'applications/metamta/garbagecollector/MetaMTAMailReceivedGarbageCollector.php',
|
||||
'MetaMTAMailSentGarbageCollector' => 'applications/metamta/garbagecollector/MetaMTAMailSentGarbageCollector.php',
|
||||
'MetaMTANotificationType' => 'applications/metamta/constants/MetaMTANotificationType.php',
|
||||
|
@ -2544,6 +2545,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSubscriptionsListController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsListController.php',
|
||||
'PhabricatorSubscriptionsTransactionController' => 'applications/subscriptions/controller/PhabricatorSubscriptionsTransactionController.php',
|
||||
'PhabricatorSubscriptionsUIEventListener' => 'applications/subscriptions/events/PhabricatorSubscriptionsUIEventListener.php',
|
||||
'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'applications/subscriptions/command/PhabricatorSubscriptionsUnsubscribeEmailCommand.php',
|
||||
'PhabricatorSupportApplication' => 'applications/support/application/PhabricatorSupportApplication.php',
|
||||
'PhabricatorSyntaxHighlighter' => 'infrastructure/markup/PhabricatorSyntaxHighlighter.php',
|
||||
'PhabricatorSyntaxHighlightingConfigOptions' => 'applications/config/option/PhabricatorSyntaxHighlightingConfigOptions.php',
|
||||
|
@ -4320,6 +4322,7 @@ phutil_register_library_map(array(
|
|||
'ManiphestTransactionSaveController' => 'ManiphestController',
|
||||
'ManiphestUpdateConduitAPIMethod' => 'ManiphestConduitAPIMethod',
|
||||
'ManiphestView' => 'AphrontView',
|
||||
'MetaMTAEmailTransactionCommand' => 'Phobject',
|
||||
'MetaMTAMailReceivedGarbageCollector' => 'PhabricatorGarbageCollector',
|
||||
'MetaMTAMailSentGarbageCollector' => 'PhabricatorGarbageCollector',
|
||||
'MetaMTANotificationType' => 'MetaMTAConstants',
|
||||
|
@ -5921,6 +5924,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSubscriptionsListController' => 'PhabricatorController',
|
||||
'PhabricatorSubscriptionsTransactionController' => 'PhabricatorController',
|
||||
'PhabricatorSubscriptionsUIEventListener' => 'PhabricatorEventListener',
|
||||
'PhabricatorSubscriptionsUnsubscribeEmailCommand' => 'MetaMTAEmailTransactionCommand',
|
||||
'PhabricatorSupportApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorSyntaxHighlightingConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorSystemActionEngine' => 'Phobject',
|
||||
|
|
|
@ -13,22 +13,4 @@ final class FileReplyHandler
|
|||
return 'F';
|
||||
}
|
||||
|
||||
protected function processMailCommands(array $commands) {
|
||||
$actor = $this->getActor();
|
||||
|
||||
$xactions = array();
|
||||
foreach ($commands as $command) {
|
||||
switch (head($command)) {
|
||||
case 'unsubscribe':
|
||||
$xaction = id(new PhabricatorFileTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||
->setNewValue(array('-' => array($actor->getPHID())));
|
||||
$xactions[] = $xaction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
abstract class MetaMTAEmailTransactionCommand extends Phobject {
|
||||
|
||||
abstract public function getCommand();
|
||||
abstract public function isCommandSupportedForObject(
|
||||
PhabricatorApplicationTransactionInterface $object);
|
||||
abstract public function buildTransactions(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorApplicationTransactionInterface $object,
|
||||
PhabricatorMetaMTAReceivedMail $mail,
|
||||
$command,
|
||||
array $argv);
|
||||
|
||||
public function getCommandAliases() {
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getCommandObjects() {
|
||||
return array($this);
|
||||
}
|
||||
|
||||
public static function getAllCommands() {
|
||||
static $commands;
|
||||
|
||||
if ($commands === null) {
|
||||
$kinds = id(new PhutilSymbolLoader())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->loadObjects();
|
||||
$commands = array();
|
||||
foreach ($kinds as $kind) {
|
||||
foreach ($kind->getCommandObjects() as $command) {
|
||||
$commands[] = $command;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
public static function getAllCommandsForObject(
|
||||
PhabricatorApplicationTransactionInterface $object) {
|
||||
|
||||
$commands = self::getAllCommands();
|
||||
foreach ($commands as $key => $command) {
|
||||
if (!$command->isCommandSupportedForObject($object)) {
|
||||
unset($commands[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
public static function getCommandMap(array $commands) {
|
||||
assert_instances_of($commands, 'MetaMTAEmailTransactionCommand');
|
||||
|
||||
$map = array();
|
||||
foreach ($commands as $command) {
|
||||
$keywords = $command->getCommandAliases();
|
||||
$keywords[] = $command->getCommand();
|
||||
|
||||
foreach ($keywords as $keyword) {
|
||||
$keyword = phutil_utf8_strtolower($keyword);
|
||||
if (empty($map[$keyword])) {
|
||||
$map[$keyword] = $command;
|
||||
} else {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Mail commands "%s" and "%s" both respond to keyword "%s". '.
|
||||
'Keywords must be uniquely associated with commands.',
|
||||
get_class($command),
|
||||
get_class($map[$keyword]),
|
||||
$keyword));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
}
|
|
@ -13,22 +13,4 @@ final class PasteReplyHandler
|
|||
return 'P';
|
||||
}
|
||||
|
||||
protected function processMailCommands(array $commands) {
|
||||
$actor = $this->getActor();
|
||||
|
||||
$xactions = array();
|
||||
foreach ($commands as $command) {
|
||||
switch (head($command)) {
|
||||
case 'unsubscribe':
|
||||
$xaction = id(new PhabricatorPasteTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||
->setNewValue(array('-' => array($actor->getPHID())));
|
||||
$xactions[] = $xaction;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorSubscriptionsUnsubscribeEmailCommand
|
||||
extends MetaMTAEmailTransactionCommand {
|
||||
|
||||
public function getCommand() {
|
||||
return 'unsubscribe';
|
||||
}
|
||||
|
||||
public function isCommandSupportedForObject(
|
||||
PhabricatorApplicationTransactionInterface $object) {
|
||||
return ($object instanceof PhabricatorSubscribableInterface);
|
||||
}
|
||||
|
||||
public function buildTransactions(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorApplicationTransactionInterface $object,
|
||||
PhabricatorMetaMTAReceivedMail $mail,
|
||||
$command,
|
||||
array $argv) {
|
||||
$xactions = array();
|
||||
|
||||
$xactions[] = $object->getApplicationTransactionTemplate()
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
|
||||
->setNewValue(
|
||||
array(
|
||||
'-' => array($viewer->getPHID()),
|
||||
));
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
}
|
|
@ -49,7 +49,9 @@ abstract class PhabricatorApplicationTransactionReplyHandler
|
|||
|
||||
$body_data = $mail->parseBody();
|
||||
|
||||
$xactions = $this->processMailCommands($body_data['commands']);
|
||||
$xactions = $this->processMailCommands(
|
||||
$mail,
|
||||
$body_data['commands']);
|
||||
|
||||
// If this object is subscribable, subscribe all the users who were
|
||||
// CC'd on the message.
|
||||
|
@ -84,9 +86,60 @@ abstract class PhabricatorApplicationTransactionReplyHandler
|
|||
->applyTransactions($target, $xactions);
|
||||
}
|
||||
|
||||
protected function processMailCommands(array $commands) {
|
||||
// TODO: Modularize this.
|
||||
return array();
|
||||
private function processMailCommands(
|
||||
PhabricatorMetaMTAReceivedMail $mail,
|
||||
array $command_list) {
|
||||
|
||||
$viewer = $this->getActor();
|
||||
$object = $this->getMailReceiver();
|
||||
|
||||
$list = MetaMTAEmailTransactionCommand::getAllCommandsForObject($object);
|
||||
$map = MetaMTAEmailTransactionCommand::getCommandMap($list);
|
||||
|
||||
$xactions = array();
|
||||
foreach ($command_list as $command_argv) {
|
||||
$command = head($command_argv);
|
||||
$argv = array_slice($command_argv, 1);
|
||||
|
||||
$handler = idx($map, phutil_utf8_strtolower($command));
|
||||
if ($handler) {
|
||||
$results = $handler->buildTransactions(
|
||||
$viewer,
|
||||
$object,
|
||||
$mail,
|
||||
$command,
|
||||
$argv);
|
||||
foreach ($results as $result) {
|
||||
$xactions[] = $result;
|
||||
}
|
||||
} else {
|
||||
$valid_commands = array();
|
||||
foreach ($list as $valid_command) {
|
||||
$aliases = $valid_command->getCommandAliases();
|
||||
if ($aliases) {
|
||||
foreach ($aliases as $key => $alias) {
|
||||
$aliases[$key] = '!'.$alias;
|
||||
}
|
||||
$aliases = implode(', ', $aliases);
|
||||
$valid_commands[] = pht(
|
||||
'!%s (or %s)',
|
||||
$valid_command->getCommand(),
|
||||
$aliases);
|
||||
} else {
|
||||
$valid_commands[] = '!'.$valid_command->getCommand();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
pht(
|
||||
'The command "!%s" is not a supported mail command. Valid '.
|
||||
'commands for this object are: %s.',
|
||||
$command,
|
||||
implode(', ', $valid_commands)));
|
||||
}
|
||||
}
|
||||
|
||||
return $xactions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue