mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-09 16:32:39 +01:00
Add basic email support to Pholio
Summary: These emails aren't yet useful, but thread/multiplex/etc correctly. Test Plan: Got some Pholio emails. Reviewers: btrahan, chad Reviewed By: btrahan CC: aran Maniphest Tasks: T2097 Differential Revision: https://secure.phabricator.com/D3842
This commit is contained in:
parent
029cfcfc19
commit
3ceaad1aa8
5 changed files with 168 additions and 13 deletions
|
@ -349,8 +349,9 @@ return array(
|
|||
// class with an implementation of your own. This will allow you to do things
|
||||
// like have a single public reply handler or change how private reply
|
||||
// handlers are generated and validated.
|
||||
//
|
||||
// This key should be set to a loadable subclass of
|
||||
// PhabricatorMailReplyHandler (and possibly of ManiphestReplyHandler).
|
||||
// PhabricatorMailReplyHandler.
|
||||
'metamta.maniphest.reply-handler' => 'ManiphestReplyHandler',
|
||||
|
||||
// If you don't want phabricator to take up an entire domain
|
||||
|
@ -367,6 +368,13 @@ return array(
|
|||
// distinguish between testing and development installs, for example.
|
||||
'metamta.maniphest.subject-prefix' => '[Maniphest]',
|
||||
|
||||
// See 'metamta.pholio.reply-handler-domain'. This does the same thing, but
|
||||
// affects Pholio.
|
||||
'metamta.pholio.reply-handler-domain' => null,
|
||||
|
||||
// Prefix prepended to mail sent by Pholio.
|
||||
'metamta.pholio.subject-prefix' => '[Pholio]',
|
||||
|
||||
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
|
||||
// but allows email replies via Differential.
|
||||
'metamta.differential.reply-handler-domain' => null,
|
||||
|
|
|
@ -1216,6 +1216,7 @@ phutil_register_library_map(array(
|
|||
'PholioMockQuery' => 'applications/pholio/query/PholioMockQuery.php',
|
||||
'PholioMockViewController' => 'applications/pholio/controller/PholioMockViewController.php',
|
||||
'PholioPixelComment' => 'applications/pholio/storage/PholioPixelComment.php',
|
||||
'PholioReplyHandler' => 'applications/pholio/mail/PholioReplyHandler.php',
|
||||
'PholioTransaction' => 'applications/pholio/storage/PholioTransaction.php',
|
||||
'PholioTransactionQuery' => 'applications/pholio/query/PholioTransactionQuery.php',
|
||||
'PholioTransactionType' => 'applications/pholio/constants/PholioTransactionType.php',
|
||||
|
@ -2427,6 +2428,7 @@ phutil_register_library_map(array(
|
|||
0 => 'PholioDAO',
|
||||
1 => 'PhabricatorMarkupInterface',
|
||||
),
|
||||
'PholioReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
'PholioTransaction' =>
|
||||
array(
|
||||
0 => 'PholioDAO',
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
final class ManiphestTransactionEditor extends PhabricatorEditor {
|
||||
|
||||
private $parentMessageID;
|
||||
private $excludePHIDs = array();
|
||||
private $auxiliaryFields = array();
|
||||
|
||||
public function setAuxiliaryFields(array $fields) {
|
||||
|
@ -20,15 +19,6 @@ final class ManiphestTransactionEditor extends PhabricatorEditor {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function setExcludePHIDs(array $exclude) {
|
||||
$this->excludePHIDs = $exclude;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExcludePHIDs() {
|
||||
return $this->excludePHIDs;
|
||||
}
|
||||
|
||||
public function applyTransactions(ManiphestTask $task, array $transactions) {
|
||||
assert_instances_of($transactions, 'ManiphestTransaction');
|
||||
|
||||
|
@ -219,7 +209,6 @@ final class ManiphestTransactionEditor extends PhabricatorEditor {
|
|||
}
|
||||
|
||||
private function sendEmail($task, $transactions, $email_to, $email_cc) {
|
||||
$exclude = $this->getExcludePHIDs();
|
||||
$email_to = array_filter(array_unique($email_to));
|
||||
$email_cc = array_filter(array_unique($email_cc));
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ final class PholioMockEditor extends PhabricatorEditor {
|
|||
"Call setContentSource() before applyTransactions()!");
|
||||
}
|
||||
|
||||
$is_new = !$mock->getID();
|
||||
|
||||
$comments = array();
|
||||
foreach ($xactions as $xaction) {
|
||||
if (strlen($xaction->getComment())) {
|
||||
|
@ -54,8 +56,12 @@ final class PholioMockEditor extends PhabricatorEditor {
|
|||
|
||||
$mentioned_phids = PhabricatorMarkupEngine::extractPHIDsFromMentions(
|
||||
$comments);
|
||||
$subscribe_phids = $mentioned_phids;
|
||||
|
||||
if ($mentioned_phids) {
|
||||
// Attempt to subscribe the actor.
|
||||
$subscribe_phids[] = $actor->getPHID();
|
||||
|
||||
if ($subscribe_phids) {
|
||||
if ($mock->getID()) {
|
||||
$old_subs = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
||||
$mock->getPHID());
|
||||
|
@ -111,11 +117,99 @@ final class PholioMockEditor extends PhabricatorEditor {
|
|||
|
||||
$mock->saveTransaction();
|
||||
|
||||
$this->sendMail($mock, $xactions, $is_new, $mentioned_phids);
|
||||
|
||||
PholioIndexer::indexMock($mock);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function sendMail(
|
||||
PholioMock $mock,
|
||||
array $xactions,
|
||||
$is_new,
|
||||
array $mentioned_phids) {
|
||||
|
||||
$subscribed_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
||||
$mock->getPHID());
|
||||
|
||||
$email_to = array(
|
||||
$mock->getAuthorPHID(),
|
||||
$this->requireActor()->getPHID(),
|
||||
);
|
||||
$email_cc = $subscribed_phids;
|
||||
|
||||
$phids = array_merge($email_to, $email_cc);
|
||||
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||
->setViewer($this->requireActor())
|
||||
->loadHandles();
|
||||
|
||||
$mock_id = $mock->getID();
|
||||
$name = $mock->getName();
|
||||
$original_name = $mock->getOriginalName();
|
||||
|
||||
$thread_id = 'pholio-mock-'.$mock->getPHID();
|
||||
|
||||
$mail_tags = $this->getMailTags($mock, $xactions);
|
||||
|
||||
$body = new PhabricatorMetaMTAMailBody();
|
||||
$body->addRawSection('lorem ipsum');
|
||||
|
||||
$mock_uri = PhabricatorEnv::getProductionURI('/M'.$mock->getID());
|
||||
|
||||
$body->addTextSection(pht('MOCK DETAIL'), $mock_uri);
|
||||
|
||||
$reply_handler = $this->buildReplyHandler($mock);
|
||||
|
||||
$template = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject("M{$mock_id}: {$name}")
|
||||
->setSubjectPrefix($this->getMailSubjectPrefix())
|
||||
->setVarySubjectPrefix('[edit/create?]')
|
||||
->setFrom($this->requireActor()->getPHID())
|
||||
->addHeader('Thread-Topic', "M{$mock_id}: {$original_name}")
|
||||
->setThreadID($thread_id, $is_new)
|
||||
->setRelatedPHID($mock->getPHID())
|
||||
->setExcludeMailRecipientPHIDs($this->getExcludeMailRecipientPHIDs())
|
||||
->setIsBulk(true)
|
||||
->setMailTags($mail_tags)
|
||||
->setBody($body->render());
|
||||
|
||||
// TODO
|
||||
// ->setParentMessageID(...)
|
||||
|
||||
$mails = $reply_handler->multiplexMail(
|
||||
$template,
|
||||
array_select_keys($handles, $email_to),
|
||||
array_select_keys($handles, $email_cc));
|
||||
|
||||
foreach ($mails as $mail) {
|
||||
$mail->saveAndSend();
|
||||
}
|
||||
|
||||
$template->addTos($email_to);
|
||||
$template->addCCs($email_cc);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
private function getMailTags(PholioMock $mock, array $xactions) {
|
||||
assert_instances_of($xactions, 'PholioTransaction');
|
||||
$tags = array();
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
public function buildReplyHandler(PholioMock $mock) {
|
||||
$handler_object = new PholioReplyHandler();
|
||||
$handler_object->setMailReceiver($mock);
|
||||
|
||||
return $handler_object;
|
||||
}
|
||||
|
||||
private function getMailSubjectPrefix() {
|
||||
return PhabricatorEnv::getEnvConfig('metamta.pholio.subject-prefix');
|
||||
}
|
||||
|
||||
private function applyTransaction(
|
||||
PholioMock $mock,
|
||||
PholioTransaction $xaction) {
|
||||
|
@ -155,6 +249,9 @@ final class PholioMockEditor extends PhabricatorEditor {
|
|||
break;
|
||||
case PholioTransactionType::TYPE_NAME:
|
||||
$mock->setName($xaction->getNewValue());
|
||||
if ($mock->getOriginalName() === null) {
|
||||
$mock->setOriginalName($xaction->getNewValue());
|
||||
}
|
||||
break;
|
||||
case PholioTransactionType::TYPE_DESCRIPTION:
|
||||
$mock->setDescription($xaction->getNewValue());
|
||||
|
|
59
src/applications/pholio/mail/PholioReplyHandler.php
Normal file
59
src/applications/pholio/mail/PholioReplyHandler.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group pholio
|
||||
*/
|
||||
final class PholioReplyHandler extends PhabricatorMailReplyHandler {
|
||||
|
||||
public function validateMailReceiver($mail_receiver) {
|
||||
if (!($mail_receiver instanceof PholioMock)) {
|
||||
throw new Exception("Mail receiver is not a PholioMock!");
|
||||
}
|
||||
}
|
||||
|
||||
public function getPrivateReplyHandlerEmailAddress(
|
||||
PhabricatorObjectHandle $handle) {
|
||||
return $this->getDefaultPrivateReplyHandlerEmailAddress($handle, 'M');
|
||||
}
|
||||
|
||||
public function getPublicReplyHandlerEmailAddress() {
|
||||
return $this->getDefaultPublicReplyHandlerEmailAddress('M');
|
||||
}
|
||||
|
||||
public function getReplyHandlerDomain() {
|
||||
return PhabricatorEnv::getEnvConfig(
|
||||
'metamta.pholio.reply-handler-domain');
|
||||
}
|
||||
|
||||
public function getReplyHandlerInstructions() {
|
||||
if ($this->supportsReplies()) {
|
||||
// TODO: Implement.
|
||||
return null;
|
||||
return "Reply to comment.";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) {
|
||||
// TODO: Implement this.
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue