[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/differential/mail/ -> DifferentialReplyHandler.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1