[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * NOTE: Do not extend this! 5 * 6 * @concrete-extensible 7 */ 8 class DifferentialReplyHandler extends PhabricatorMailReplyHandler { 9 10 private $receivedMail; 11 12 public function validateMailReceiver($mail_receiver) { 13 if (!($mail_receiver instanceof DifferentialRevision)) { 14 throw new Exception('Receiver is not a DifferentialRevision!'); 15 } 16 } 17 18 public function getPrivateReplyHandlerEmailAddress( 19 PhabricatorObjectHandle $handle) { 20 return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'D'); 21 } 22 23 public function getPublicReplyHandlerEmailAddress() { 24 return $this->getDefaultPublicReplyHandlerEmailAddress('D'); 25 } 26 27 public function getReplyHandlerDomain() { 28 return PhabricatorEnv::getEnvConfig( 29 'metamta.differential.reply-handler-domain'); 30 } 31 32 /* 33 * Generate text like the following from the supported commands. 34 * " 35 * 36 * ACTIONS 37 * Reply to comment, or !accept, !reject, !abandon, !resign, !reclaim. 38 * 39 * " 40 */ 41 public function getReplyHandlerInstructions() { 42 if (!$this->supportsReplies()) { 43 return null; 44 } 45 46 $supported_commands = $this->getSupportedCommands(); 47 $text = ''; 48 if (empty($supported_commands)) { 49 return $text; 50 } 51 52 $comment_command_printed = false; 53 if (in_array(DifferentialAction::ACTION_COMMENT, $supported_commands)) { 54 $text .= pht('Reply to comment'); 55 $comment_command_printed = true; 56 57 $supported_commands = array_diff( 58 $supported_commands, array(DifferentialAction::ACTION_COMMENT)); 59 } 60 61 if (!empty($supported_commands)) { 62 if ($comment_command_printed) { 63 $text .= ', or '; 64 } 65 66 $modified_commands = array(); 67 foreach ($supported_commands as $command) { 68 $modified_commands[] = '!'.$command; 69 } 70 71 $text .= implode(', ', $modified_commands); 72 } 73 74 $text .= '.'; 75 76 return $text; 77 } 78 79 public function getSupportedCommands() { 80 $actions = array( 81 DifferentialAction::ACTION_COMMENT, 82 DifferentialAction::ACTION_REJECT, 83 DifferentialAction::ACTION_ABANDON, 84 DifferentialAction::ACTION_RECLAIM, 85 DifferentialAction::ACTION_RESIGN, 86 DifferentialAction::ACTION_RETHINK, 87 'unsubscribe', 88 ); 89 90 if (PhabricatorEnv::getEnvConfig('differential.enable-email-accept')) { 91 $actions[] = DifferentialAction::ACTION_ACCEPT; 92 } 93 94 return $actions; 95 } 96 97 protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { 98 $this->receivedMail = $mail; 99 $this->handleAction($mail->getCleanTextBody(), $mail->getAttachments()); 100 } 101 102 public function handleAction($body, array $attachments) { 103 // all commands start with a bang and separated from the body by a newline 104 // to make sure that actual feedback text couldn't trigger an action. 105 // unrecognized commands will be parsed as part of the comment. 106 $command = DifferentialAction::ACTION_COMMENT; 107 $supported_commands = $this->getSupportedCommands(); 108 $regex = "/\A\n*!(".implode('|', $supported_commands).")\n*/"; 109 $matches = array(); 110 if (preg_match($regex, $body, $matches)) { 111 $command = $matches[1]; 112 $body = trim(str_replace('!'.$command, '', $body)); 113 } 114 115 $actor = $this->getActor(); 116 if (!$actor) { 117 throw new Exception('No actor is set for the reply action.'); 118 } 119 120 switch ($command) { 121 case 'unsubscribe': 122 id(new PhabricatorSubscriptionsEditor()) 123 ->setActor($actor) 124 ->setObject($this->getMailReceiver()) 125 ->unsubscribe(array($actor->getPHID())) 126 ->save(); 127 // TODO: Send the user a confirmation email? 128 return null; 129 } 130 131 $body = $this->enhanceBodyWithAttachments($body, $attachments); 132 133 $xactions = array(); 134 135 if ($command && ($command != DifferentialAction::ACTION_COMMENT)) { 136 $xactions[] = id(new DifferentialTransaction()) 137 ->setTransactionType(DifferentialTransaction::TYPE_ACTION) 138 ->setNewValue($command); 139 } 140 141 if (strlen($body)) { 142 $xactions[] = id(new DifferentialTransaction()) 143 ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 144 ->attachComment( 145 id(new DifferentialTransactionComment()) 146 ->setContent($body)); 147 } 148 149 $editor = id(new DifferentialTransactionEditor()) 150 ->setActor($actor) 151 ->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs()) 152 ->setContinueOnMissingFields(true) 153 ->setContinueOnNoEffect(true); 154 155 // NOTE: We have to be careful about this because Facebook's 156 // implementation jumps straight into handleAction() and will not have 157 // a PhabricatorMetaMTAReceivedMail object. 158 if ($this->receivedMail) { 159 $content_source = PhabricatorContentSource::newForSource( 160 PhabricatorContentSource::SOURCE_EMAIL, 161 array( 162 'id' => $this->receivedMail->getID(), 163 )); 164 $editor->setContentSource($content_source); 165 $editor->setParentMessageID($this->receivedMail->getMessageID()); 166 } else { 167 $content_source = PhabricatorContentSource::newForSource( 168 PhabricatorContentSource::SOURCE_LEGACY, 169 array()); 170 $editor->setContentSource($content_source); 171 } 172 173 $editor->applyTransactions($this->getMailReceiver(), $xactions); 174 } 175 176 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |