@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Maniphest - add support for !assign command

Summary:
also try to centralize some of the command parsing logic. note that differential is still an exception here. it uses a whitelist-style regex. i think long-term we should have this for every app but changing it seemed too big for this diff.

Fixes T3937.

Test Plan:
echo '!assign btrahan' | ./bin/mail receive-test --as xerxes --to T22 ; echo '!claim' | ./bin/mail receive-test --as xerxes --to T22

unit tests passed, though my new one is silly

Reviewers: epriestley

Reviewed By: epriestley

CC: Korvin, epriestley, aran

Maniphest Tasks: T3937

Differential Revision: https://secure.phabricator.com/D7307

+120 -56
-1
src/applications/conpherence/mail/ConpherenceReplyHandler.php
··· 69 69 ->setParentMessageID($mail->getMessageID()); 70 70 71 71 $body = $mail->getCleanTextBody(); 72 - $body = trim($body); 73 72 $file_phids = $mail->getAttachments(); 74 73 $body = $this->enhanceBodyWithAttachments( 75 74 $body,
+3 -14
src/applications/files/mail/FileReplyHandler.php
··· 32 32 $actor = $this->getActor(); 33 33 $file = $this->getMailReceiver(); 34 34 35 - $body = $mail->getCleanTextBody(); 36 - $body = trim($body); 35 + $body_data = $mail->parseBody(); 36 + $body = $body_data['body']; 37 37 $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); 38 38 39 39 $content_source = PhabricatorContentSource::newForSource( ··· 42 42 'id' => $mail->getID(), 43 43 )); 44 44 45 - $lines = explode("\n", trim($body)); 46 - $first_line = head($lines); 47 - 48 45 $xactions = array(); 49 - $command = null; 50 - $matches = null; 51 - if (preg_match('/^!(\w+)/', $first_line, $matches)) { 52 - $lines = array_slice($lines, 1); 53 - $body = implode("\n", $lines); 54 - $body = trim($body); 55 - 56 - $command = $matches[1]; 57 - } 46 + $command = $body_data['body']; 58 47 59 48 switch ($command) { 60 49 case 'unsubscribe':
+3 -13
src/applications/legalpad/mail/LegalpadReplyHandler.php
··· 37 37 $actor = $this->getActor(); 38 38 $document = $this->getMailReceiver(); 39 39 40 - $body = $mail->getCleanTextBody(); 41 - $body = trim($body); 40 + $body_data = $mail->parseBody(); 41 + $body = $body_data['body']; 42 42 $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); 43 43 44 44 $content_source = PhabricatorContentSource::newForSource( ··· 47 47 'id' => $mail->getID(), 48 48 )); 49 49 50 - $lines = explode("\n", trim($body)); 51 - $first_line = head($lines); 52 50 53 51 $xactions = array(); 54 - $command = null; 55 - $matches = null; 56 - if (preg_match('/^!(\w+)/', $first_line, $matches)) { 57 - $lines = array_slice($lines, 1); 58 - $body = implode("\n", $lines); 59 - $body = trim($body); 60 - 61 - $command = $matches[1]; 62 - } 52 + $command = $body_data['command']; 63 53 64 54 switch ($command) { 65 55 case 'unsubscribe':
+21 -13
src/applications/maniphest/mail/ManiphestReplyHandler.php
··· 45 45 46 46 $user = $this->getActor(); 47 47 48 - $body = $mail->getCleanTextBody(); 49 - $body = trim($body); 48 + $body_data = $mail->parseBody(); 49 + $body = $body_data['body']; 50 50 $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); 51 51 52 52 $xactions = array(); ··· 73 73 $task->setPriority(ManiphestTaskPriority::getDefaultPriority()); 74 74 75 75 } else { 76 - $lines = explode("\n", trim($body)); 77 - $first_line = head($lines); 78 76 79 - $command = null; 80 - $matches = null; 81 - if (preg_match('/^!(\w+)/', $first_line, $matches)) { 82 - $lines = array_slice($lines, 1); 83 - $body = implode("\n", $lines); 84 - $body = trim($body); 85 - 86 - $command = $matches[1]; 87 - } 77 + $command = $body_data['command']; 78 + $command_value = $body_data['command_value']; 88 79 89 80 $ttype = PhabricatorTransactions::TYPE_COMMENT; 90 81 $new_value = null; ··· 96 87 case 'claim': 97 88 $ttype = ManiphestTransaction::TYPE_OWNER; 98 89 $new_value = $user->getPHID(); 90 + break; 91 + case 'assign': 92 + $ttype = ManiphestTransaction::TYPE_OWNER; 93 + if ($command_value) { 94 + $assign_users = id(new PhabricatorPeopleQuery()) 95 + ->setViewer($user) 96 + ->withUsernames(array($command_value)) 97 + ->execute(); 98 + if ($assign_users) { 99 + $assign_user = head($assign_users); 100 + $new_value = $assign_user->getPHID(); 101 + } 102 + } 103 + // assign to the user by default 104 + if (!$new_value) { 105 + $new_value = $user->getPHID(); 106 + } 99 107 break; 100 108 case 'unsubscribe': 101 109 $is_unsub = true;
+44 -1
src/applications/metamta/parser/PhabricatorMetaMTAEmailBodyParser.php
··· 2 2 3 3 final class PhabricatorMetaMTAEmailBodyParser { 4 4 5 + /** 6 + * Mails can have bodies such as 7 + * 8 + * !claim 9 + * 10 + * taking this task 11 + * 12 + * Or 13 + * 14 + * !assign epriestley 15 + * 16 + * please, take this task I took; its hard 17 + * 18 + * This function parses such an email body and returns a dictionary 19 + * containing a clean body text (e.g. "taking this task"), a $command 20 + * (e.g. !claim, !assign) and a $command_value (e.g. "epriestley" in the 21 + * !assign example.) 22 + * 23 + * @return dict 24 + */ 25 + public function parseBody($body) { 26 + $body = $this->stripTextBody($body); 27 + $lines = explode("\n", trim($body)); 28 + $first_line = head($lines); 29 + 30 + $command = null; 31 + $command_value = null; 32 + $matches = null; 33 + if (preg_match('/^!(\w+)\s*(\S+)?/', $first_line, $matches)) { 34 + $lines = array_slice($lines, 1); 35 + $body = implode("\n", $lines); 36 + $body = trim($body); 37 + 38 + $command = $matches[1]; 39 + $command_value = idx($matches, 2); 40 + } 41 + 42 + return array( 43 + 'body' => $body, 44 + 'command' => $command, 45 + 'command_value' => $command_value); 46 + } 47 + 5 48 public function stripTextBody($body) { 6 - return $this->stripSignature($this->stripQuotedText($body)); 49 + return trim($this->stripSignature($this->stripQuotedText($body))); 7 50 } 8 51 9 52 private function stripQuotedText($body) {
+38
src/applications/metamta/parser/__tests__/PhabricatorMetaMTAEmailBodyParserTestCase.php
··· 12 12 } 13 13 } 14 14 15 + public function testEmailBodyCommandParsing() { 16 + $bodies = $this->getEmailBodiesWithFullCommands(); 17 + foreach ($bodies as $body) { 18 + $parser = new PhabricatorMetaMTAEmailBodyParser(); 19 + $body_data = $parser->parseBody($body); 20 + $this->assertEqual('OKAY', $body_data['body']); 21 + $this->assertEqual('whatevs', $body_data['command']); 22 + $this->assertEqual('dude', $body_data['command_value']); 23 + } 24 + $bodies = $this->getEmailBodiesWithPartialCommands(); 25 + foreach ($bodies as $body) { 26 + $parser = new PhabricatorMetaMTAEmailBodyParser(); 27 + $body_data = $parser->parseBody($body); 28 + $this->assertEqual('OKAY', $body_data['body']); 29 + $this->assertEqual('whatevs', $body_data['command']); 30 + $this->assertEqual(null, $body_data['command_value']); 31 + } 32 + } 33 + 34 + private function getEmailBodiesWithFullCommands() { 35 + $bodies = $this->getEmailBodies(); 36 + $with_commands = array(); 37 + foreach ($bodies as $body) { 38 + $with_commands[] = "!whatevs dude\n" . $body; 39 + } 40 + return $with_commands; 41 + } 42 + 43 + private function getEmailBodiesWithPartialCommands() { 44 + $bodies = $this->getEmailBodies(); 45 + $with_commands = array(); 46 + foreach ($bodies as $body) { 47 + $with_commands[] = "!whatevs\n" . $body; 48 + } 49 + return $with_commands; 50 + } 51 + 52 + 15 53 private function getEmailBodies() { 16 54 $trailing_space = ' '; 17 55
+1 -1
src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
··· 307 307 return $this->getSingleReplyHandlerPrefix($address); 308 308 } 309 309 310 - final protected function enhanceBodyWithAttachments( 310 + final protected function enhanceBodyWithAttachments( 311 311 $body, 312 312 array $attachments, 313 313 $format = '- {F%d, layout=link}') {
+7 -2
src/applications/metamta/storage/PhabricatorMetaMTAReceivedMail.php
··· 120 120 } 121 121 122 122 public function getCleanTextBody() { 123 - $body = idx($this->bodies, 'text'); 123 + $body = $this->getRawTextBody(); 124 + $parser = new PhabricatorMetaMTAEmailBodyParser(); 125 + return $parser->stripTextBody($body); 126 + } 124 127 128 + public function parseBody() { 129 + $body = $this->getRawTextBody(); 125 130 $parser = new PhabricatorMetaMTAEmailBodyParser(); 126 - return $parser->stripTextBody($body); 131 + return $parser->parseBody($body); 127 132 } 128 133 129 134 public function getRawTextBody() {
+3 -11
src/applications/paste/mail/PasteReplyHandler.php
··· 32 32 $actor = $this->getActor(); 33 33 $paste = $this->getMailReceiver(); 34 34 35 - $body = $mail->getCleanTextBody(); 36 - $body = trim($body); 35 + $body_data = $mail->parseBody(); 36 + $body = $body_data['body']; 37 37 $body = $this->enhanceBodyWithAttachments($body, $mail->getAttachments()); 38 38 39 39 $content_source = PhabricatorContentSource::newForSource( ··· 46 46 $first_line = head($lines); 47 47 48 48 $xactions = array(); 49 - $command = null; 50 - $matches = null; 51 - if (preg_match('/^!(\w+)/', $first_line, $matches)) { 52 - $lines = array_slice($lines, 1); 53 - $body = implode("\n", $lines); 54 - $body = trim($body); 55 - 56 - $command = $matches[1]; 57 - } 49 + $command = $body_data['command']; 58 50 59 51 switch ($command) { 60 52 case 'unsubscribe':