From 161f936871b8b1a2557a39d604730d692e62efae Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 1 Apr 2015 08:39:21 -0700 Subject: [PATCH] Lift common code for transaction-based reply handlers into parent class Summary: Ref T7199. Essentially all of the reply handlers now apply transactions to something which implements PhabricatorApplicationTransactionInterface. We can share code between them by lifting this stuff into a superclass. First, convert paste. Also rename `PasteMockMailReceiver` to `PasteMailReceiver` (this got mis-copied from Pholio at some point, I think). Test Plan: Used `bin/mail receive-test` to send comments + `!unsubscribe` to pastes. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7199 Differential Revision: https://secure.phabricator.com/D12236 --- src/__phutil_library_map__.php | 8 +- ...MailReceiver.php => PasteMailReceiver.php} | 2 +- .../paste/mail/PasteReplyHandler.php | 46 ++-------- ...atorApplicationTransactionReplyHandler.php | 92 +++++++++++++++++++ 4 files changed, 105 insertions(+), 43 deletions(-) rename src/applications/paste/mail/{PasteMockMailReceiver.php => PasteMailReceiver.php} (92%) create mode 100644 src/applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 919eb5342e..5f57a34b64 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1248,7 +1248,7 @@ phutil_register_library_map(array( 'PasteDefaultViewCapability' => 'applications/paste/capability/PasteDefaultViewCapability.php', 'PasteEmbedView' => 'applications/paste/view/PasteEmbedView.php', 'PasteInfoConduitAPIMethod' => 'applications/paste/conduit/PasteInfoConduitAPIMethod.php', - 'PasteMockMailReceiver' => 'applications/paste/mail/PasteMockMailReceiver.php', + 'PasteMailReceiver' => 'applications/paste/mail/PasteMailReceiver.php', 'PasteQueryConduitAPIMethod' => 'applications/paste/conduit/PasteQueryConduitAPIMethod.php', 'PasteReplyHandler' => 'applications/paste/mail/PasteReplyHandler.php', 'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php', @@ -1310,6 +1310,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionNoEffectException' => 'applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php', 'PhabricatorApplicationTransactionNoEffectResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionNoEffectResponse.php', 'PhabricatorApplicationTransactionQuery' => 'applications/transactions/query/PhabricatorApplicationTransactionQuery.php', + 'PhabricatorApplicationTransactionReplyHandler' => 'applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php', 'PhabricatorApplicationTransactionResponse' => 'applications/transactions/response/PhabricatorApplicationTransactionResponse.php', 'PhabricatorApplicationTransactionShowOlderController' => 'applications/transactions/controller/PhabricatorApplicationTransactionShowOlderController.php', 'PhabricatorApplicationTransactionStructureException' => 'applications/transactions/exception/PhabricatorApplicationTransactionStructureException.php', @@ -4512,9 +4513,9 @@ phutil_register_library_map(array( 'PasteDefaultViewCapability' => 'PhabricatorPolicyCapability', 'PasteEmbedView' => 'AphrontView', 'PasteInfoConduitAPIMethod' => 'PasteConduitAPIMethod', - 'PasteMockMailReceiver' => 'PhabricatorObjectMailReceiver', + 'PasteMailReceiver' => 'PhabricatorObjectMailReceiver', 'PasteQueryConduitAPIMethod' => 'PasteConduitAPIMethod', - 'PasteReplyHandler' => 'PhabricatorMailReplyHandler', + 'PasteReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler', 'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', 'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', 'PeopleUserLogGarbageCollector' => 'PhabricatorGarbageCollector', @@ -4579,6 +4580,7 @@ phutil_register_library_map(array( 'PhabricatorApplicationTransactionNoEffectException' => 'Exception', 'PhabricatorApplicationTransactionNoEffectResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', + 'PhabricatorApplicationTransactionReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorApplicationTransactionResponse' => 'AphrontProxyResponse', 'PhabricatorApplicationTransactionShowOlderController' => 'PhabricatorApplicationTransactionController', 'PhabricatorApplicationTransactionStructureException' => 'Exception', diff --git a/src/applications/paste/mail/PasteMockMailReceiver.php b/src/applications/paste/mail/PasteMailReceiver.php similarity index 92% rename from src/applications/paste/mail/PasteMockMailReceiver.php rename to src/applications/paste/mail/PasteMailReceiver.php index 6a56db71d8..73d27ecc17 100644 --- a/src/applications/paste/mail/PasteMockMailReceiver.php +++ b/src/applications/paste/mail/PasteMailReceiver.php @@ -1,6 +1,6 @@ getDefaultPrivateReplyHandlerEmailAddress($handle, 'P'); + public function getObjectPrefix() { + return 'P'; } - public function getPublicReplyHandlerEmailAddress() { - return $this->getDefaultPublicReplyHandlerEmailAddress('P'); - } - - protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { - $actor = $this->getActor(); - $paste = $this->getMailReceiver(); - - $body_data = $mail->parseBody(); - $body = $body_data['body']; - $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); - - $content_source = PhabricatorContentSource::newForSource( - PhabricatorContentSource::SOURCE_EMAIL, - array( - 'id' => $mail->getID(), - )); - - $lines = explode("\n", trim($body)); - $first_line = head($lines); + protected function processMailCommands(array $commands) { + $actor = $this->getActor(); $xactions = array(); - - $commands = $body_data['commands']; foreach ($commands as $command) { switch (head($command)) { case 'unsubscribe': @@ -48,19 +28,7 @@ final class PasteReplyHandler extends PhabricatorMailReplyHandler { } } - $xactions[] = id(new PhabricatorPasteTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) - ->attachComment( - id(new PhabricatorPasteTransactionComment()) - ->setContent($body)); - - $editor = id(new PhabricatorPasteEditor()) - ->setActor($actor) - ->setContentSource($content_source) - ->setContinueOnNoEffect(true) - ->setIsPreview(false); - - $editor->applyTransactions($paste, $xactions); + return $xactions; } } diff --git a/src/applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php b/src/applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php new file mode 100644 index 0000000000..fbfeb6303f --- /dev/null +++ b/src/applications/transactions/replyhandler/PhabricatorApplicationTransactionReplyHandler.php @@ -0,0 +1,92 @@ +getDefaultPrivateReplyHandlerEmailAddress( + $handle, + $this->getObjectPrefix()); + } + + public function getPublicReplyHandlerEmailAddress() { + return $this->getDefaultPublicReplyHandlerEmailAddress( + $this->getObjectPrefix()); + } + + private function newEditor(PhabricatorMetaMTAReceivedMail $mail) { + $content_source = PhabricatorContentSource::newForSource( + PhabricatorContentSource::SOURCE_EMAIL, + array( + 'id' => $mail->getID(), + )); + + $editor = $this->getMailReceiver() + ->getApplicationTransactionEditor() + ->setActor($this->getActor()) + ->setContentSource($content_source) + ->setContinueOnMissingFields(true) + ->setParentMessageID($mail->getMessageID()) + ->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs()); + + if ($this->getApplicationEmail()) { + $editor->setApplicationEmail($this->getApplicationEmail()); + } + + return $editor; + } + + private function newTransaction() { + return $this->getMailReceiver()->getApplicationTransactionTemplate(); + } + + final protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { + $viewer = $this->getActor(); + $object = $this->getMailReceiver(); + + $body_data = $mail->parseBody(); + + $xactions = $this->processMailCommands($body_data['commands']); + + // If this object is subscribable, subscribe all the users who were + // CC'd on the message. + if ($object instanceof PhabricatorSubscribableInterface) { + $subscriber_phids = $mail->loadCCPHIDs(); + if ($subscriber_phids) { + $xactions[] = $this->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) + ->setNewValue( + array( + '+' => array($viewer->getPHID()), + )); + } + } + + $body = $body_data['body']; + $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); + + $comment = $this + ->newTransaction() + ->getApplicationTransactionCommentObject() + ->setContent($body); + + $xactions[] = $this->newTransaction() + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) + ->attachComment($comment); + + $target = $object->getApplicationTransactionObject(); + + $this->newEditor($mail) + ->setContinueOnNoEffect(true) + ->applyTransactions($target, $xactions); + } + + protected function processMailCommands(array $commands) { + // TODO: Modularize this. + return array(); + } + +}