Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F18767164
D11329.id27202.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
26 KB
Referenced Files
None
Subscribers
None
D11329.id27202.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1274,6 +1274,7 @@
'PhabricatorApplicationTransactionController' => 'applications/transactions/controller/PhabricatorApplicationTransactionController.php',
'PhabricatorApplicationTransactionDetailController' => 'applications/transactions/controller/PhabricatorApplicationTransactionDetailController.php',
'PhabricatorApplicationTransactionEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionEditor.php',
+ 'PhabricatorApplicationTransactionEmailWorker' => 'applications/transactions/worker/PhabricatorApplicationTransactionEmailWorker.php',
'PhabricatorApplicationTransactionFeedStory' => 'applications/transactions/feed/PhabricatorApplicationTransactionFeedStory.php',
'PhabricatorApplicationTransactionInterface' => 'applications/transactions/interface/PhabricatorApplicationTransactionInterface.php',
'PhabricatorApplicationTransactionNoEffectException' => 'applications/transactions/exception/PhabricatorApplicationTransactionNoEffectException.php',
@@ -1930,6 +1931,7 @@
'PhabricatorManiphestApplication' => 'applications/maniphest/application/PhabricatorManiphestApplication.php',
'PhabricatorManiphestConfigOptions' => 'applications/maniphest/config/PhabricatorManiphestConfigOptions.php',
'PhabricatorManiphestTaskTestDataGenerator' => 'applications/maniphest/lipsum/PhabricatorManiphestTaskTestDataGenerator.php',
+ 'PhabricatorManiphestTransactionEmailWorker' => 'applications/maniphest/worker/PhabricatorManiphestTransactionEmailWorker.php',
'PhabricatorMarkupCache' => 'applications/cache/storage/PhabricatorMarkupCache.php',
'PhabricatorMarkupEngine' => 'infrastructure/markup/PhabricatorMarkupEngine.php',
'PhabricatorMarkupInterface' => 'infrastructure/markup/PhabricatorMarkupInterface.php',
@@ -4435,6 +4437,7 @@
'PhabricatorApplicationTransactionController' => 'PhabricatorController',
'PhabricatorApplicationTransactionDetailController' => 'PhabricatorApplicationTransactionController',
'PhabricatorApplicationTransactionEditor' => 'PhabricatorEditor',
+ 'PhabricatorApplicationTransactionEmailWorker' => 'PhabricatorWorker',
'PhabricatorApplicationTransactionFeedStory' => 'PhabricatorFeedStory',
'PhabricatorApplicationTransactionNoEffectException' => 'Exception',
'PhabricatorApplicationTransactionNoEffectResponse' => 'AphrontProxyResponse',
@@ -5125,6 +5128,7 @@
'PhabricatorManiphestApplication' => 'PhabricatorApplication',
'PhabricatorManiphestConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorManiphestTaskTestDataGenerator' => 'PhabricatorTestDataGenerator',
+ 'PhabricatorManiphestTransactionEmailWorker' => 'PhabricatorApplicationTransactionEmailWorker',
'PhabricatorMarkupCache' => 'PhabricatorCacheDAO',
'PhabricatorMarkupOneOff' => 'PhabricatorMarkupInterface',
'PhabricatorMarkupPreviewController' => 'PhabricatorController',
diff --git a/src/applications/maniphest/editor/ManiphestTransactionEditor.php b/src/applications/maniphest/editor/ManiphestTransactionEditor.php
--- a/src/applications/maniphest/editor/ManiphestTransactionEditor.php
+++ b/src/applications/maniphest/editor/ManiphestTransactionEditor.php
@@ -13,6 +13,10 @@
return pht('Maniphest Tasks');
}
+ protected function getTransactionEmailWorkerClass() {
+ return 'PhabricatorManiphestTransactionEmailWorker';
+ }
+
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
@@ -406,13 +410,13 @@
return $xactions;
}
- protected function getMailSubjectPrefix() {
+ /* protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.maniphest.subject-prefix');
}
protected function getMailThreadID(PhabricatorLiskDAO $object) {
return 'maniphest-task-'.$object->getPHID();
- }
+ }*/
protected function getMailTo(PhabricatorLiskDAO $object) {
return array(
@@ -435,7 +439,7 @@
return $phids;
}
- public function getMailTagsMap() {
+ /* public function getMailTagsMap() {
return array(
ManiphestTransaction::MAILTAG_STATUS =>
pht("A task's status changes."),
@@ -456,23 +460,23 @@
ManiphestTransaction::MAILTAG_OTHER =>
pht('Other task activity not listed above occurs.'),
);
- }
+ }*/
- protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+ /* protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new ManiphestReplyHandler())
->setMailReceiver($object);
- }
+ }*/
- protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ /* protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$id = $object->getID();
$title = $object->getTitle();
return id(new PhabricatorMetaMTAMail())
->setSubject("T{$id}: {$title}")
->addHeader('Thread-Topic', "T{$id}: ".$object->getOriginalTitle());
- }
+ }*/
- protected function buildMailBody(
+ /* protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
@@ -517,7 +521,7 @@
return $body;
- }
+ }*/
protected function shouldPublishFeedStory(
PhabricatorLiskDAO $object,
@@ -549,6 +553,7 @@
HeraldTranscript $transcript) {
$this->heraldEmailPHIDs = $adapter->getEmailPHIDs();
+
$xactions = array();
$cc_phids = $adapter->getCcPHIDs();
diff --git a/src/applications/maniphest/worker/PhabricatorManiphestTransactionEmailWorker.php b/src/applications/maniphest/worker/PhabricatorManiphestTransactionEmailWorker.php
new file mode 100644
--- /dev/null
+++ b/src/applications/maniphest/worker/PhabricatorManiphestTransactionEmailWorker.php
@@ -0,0 +1,113 @@
+<?php
+
+final class PhabricatorManiphestTransactionEmailWorker
+ extends PhabricatorApplicationTransactionEmailWorker {
+
+ protected function loadObject($phid) {
+ $task = id(new ManiphestTaskQuery())
+ ->withPHIDs(array($phid))
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->executeOne();
+ return $task;
+ }
+
+ protected function loadXActions($xactions) {
+ $xactions = id(new ManiphestTransactionQuery())
+ ->withPHIDs($xactions)
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->execute();
+ return $xactions;
+ }
+
+ protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+ return id(new ManiphestReplyHandler())
+ ->setMailReceiver($object);
+ }
+
+ protected function getMailSubjectPrefix() {
+ return PhabricatorEnv::getEnvConfig('metamta.maniphest.subject-prefix');
+ }
+
+ protected function getMailThreadID(PhabricatorLiskDAO $object) {
+ return 'maniphest-task-'.$object->getPHID();
+ }
+
+ public function getMailTagsMap() {
+ return array(
+ ManiphestTransaction::MAILTAG_STATUS =>
+ pht("A task's status changes."),
+ ManiphestTransaction::MAILTAG_OWNER =>
+ pht("A task's owner changes."),
+ ManiphestTransaction::MAILTAG_PRIORITY =>
+ pht("A task's priority changes."),
+ ManiphestTransaction::MAILTAG_CC =>
+ pht("A task's subscribers change."),
+ ManiphestTransaction::MAILTAG_PROJECTS =>
+ pht("A task's associated projects change."),
+ ManiphestTransaction::MAILTAG_UNBLOCK =>
+ pht('One of the tasks a task is blocked by changes status.'),
+ ManiphestTransaction::MAILTAG_COLUMN =>
+ pht('A task is moved between columns on a workboard.'),
+ ManiphestTransaction::MAILTAG_COMMENT =>
+ pht('Someone comments on a task.'),
+ ManiphestTransaction::MAILTAG_OTHER =>
+ pht('Other task activity not listed above occurs.'),
+ );
+ }
+
+ protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ $id = $object->getID();
+ $title = $object->getTitle();
+
+ return id(new PhabricatorMetaMTAMail())
+ ->setSubject("T{$id}: {$title}")
+ ->addHeader('Thread-Topic', "T{$id}: ".$object->getOriginalTitle());
+ }
+
+ protected function buildMailBody(
+ PhabricatorLiskDAO $object,
+ array $xactions,
+ PhabricatorUser $viewer) {
+
+ $body = parent::buildMailBody($object, $xactions, $viewer);
+
+ if ($this->getIsNewObject()) {
+ $body->addTextSection(
+ pht('TASK DESCRIPTION'),
+ $object->getDescription());
+ }
+
+ $body->addLinkSection(
+ pht('TASK DETAIL'),
+ PhabricatorEnv::getProductionURI('/T'.$object->getID()));
+
+
+ $board_phids = array();
+ $type_column = ManiphestTransaction::TYPE_PROJECT_COLUMN;
+ foreach ($xactions as $xaction) {
+ if ($xaction->getTransactionType() == $type_column) {
+ $new = $xaction->getNewValue();
+ $project_phid = idx($new, 'projectPHID');
+ if ($project_phid) {
+ $board_phids[] = $project_phid;
+ }
+ }
+ }
+
+ if ($board_phids) {
+ $projects = id(new PhabricatorProjectQuery())
+ ->setViewer($viewer)
+ ->withPHIDs($board_phids)
+ ->execute();
+
+ foreach ($projects as $project) {
+ $body->addLinkSection(
+ pht('WORKBOARD'),
+ PhabricatorEnv::getProductionURI(
+ '/project/board/'.$project->getID().'/'));
+ }
+ }
+
+ return $body;
+ }
+}
diff --git a/src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php b/src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
--- a/src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
+++ b/src/applications/metamta/replyhandler/PhabricatorMailReplyHandler.php
@@ -197,6 +197,35 @@
// for now.
$recipients = $tos + $ccs;
+ // Check if all recipients have proper permissions to the object
+ // Remove them from the list otherwise
+ $recipient_users = id(new PhabricatorPeopleQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs(array_keys($recipients))
+ ->execute();
+ $recipient_users = mpull($recipient_users, null, 'getPHID');
+
+ // Check if user has permissions to view this object
+ foreach ($recipients as $phid => $recipient) {
+ if ($this->mailReceiver
+ && $this->mailReceiver instanceof PhabricatorPolicyInterface
+ && idx($recipient_users, $phid)
+ && $recipient_users[$phid] instanceof PhabricatorUser) {
+ if (!PhabricatorPolicyFilter::hasCapability(
+ $recipient_users[$phid],
+ $this->mailReceiver,
+ PhabricatorPolicyCapability::CAN_VIEW)) {
+ // User has no permission to this object
+ // so remove them from the recipient list
+ unset($recipients[$phid]);
+ }
+ }
+ }
+
+ if (!$recipients) {
+ return $result;
+ }
+
// When multiplexing mail, explicitly include To/Cc information in the
// message body and headers.
diff --git a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
--- a/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
+++ b/src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
@@ -29,6 +29,7 @@
private $actingAsPHID;
private $disableEmail;
+ protected $emailData;
/**
* Get the class name for the application this editor is a part of.
@@ -794,6 +795,7 @@
$mail = null;
if (!$this->getDisableEmail()) {
if ($this->shouldSendMail($object, $xactions)) {
+ // FIXME: fix the $mail recipient list for the feed
$mail = $this->sendMail($object, $xactions);
}
}
@@ -1906,6 +1908,11 @@
return false;
}
+ // FIXME: Make abstract?
+ protected function getTransactionEmailWorkerClass() {
+ throw new Exception('This function needs to be implemented to be able to render Email');
+ }
+
/**
* @task mail
@@ -1916,7 +1923,6 @@
// Check if any of the transactions are visible. If we don't have any
// visible transactions, don't send the mail.
-
$any_visible = false;
foreach ($xactions as $xaction) {
if (!$xaction->shouldHideForMail($xactions)) {
@@ -1929,10 +1935,39 @@
return;
}
+ $herald_xscript = $this->getHeraldTranscript();
+ if ($herald_xscript) {
+ $herald_header = $herald_xscript->getXHeraldRulesHeader();
+ $herald_header = HeraldTranscript::saveXHeraldRulesHeader(
+ $object->getPHID(),
+ $herald_header);
+ } else {
+ $herald_header = HeraldTranscript::loadXHeraldRulesHeader(
+ $object->getPHID());
+ }
+
+ PhabricatorWorker::scheduleTask(
+ $this->getTransactionEmailWorkerClass(),
+ array(
+ 'object' => $object->getPHID(),
+ 'xactions' => mpull($xactions, 'getPHID'),
+ 'mailTo' => $this->getMailTo($object),
+ 'mailCC' => $this->getMailCC($object),
+ 'actingAsPHID' => $this->getActingAsPHID(),
+ 'isNewObject' => $this->getIsNewObject(),
+ 'heraldHeader' => $herald_header,
+ 'excludeMailRecipientPHIDs' => $this->getExcludeMailRecipientPHIDs(),
+ 'parentMessageID' => $this->getParentMessageID(),
+ ),
+ array(
+ 'priority' => PhabricatorWorker::PRIORITY_ALERTS, // FIXME: right prio?
+ ));
+
+ /*
$email_to = array_filter(array_unique($this->getMailTo($object)));
$email_cc = array_filter(array_unique($this->getMailCC($object)));
-
$phids = array_merge($email_to, $email_cc);
+
$handles = id(new PhabricatorHandleQuery())
->setViewer($this->requireActor())
->withPHIDs($phids)
@@ -2003,10 +2038,12 @@
$template->addTos($email_to);
$template->addCCs($email_cc);
- return $template;
+ return $template;*/
+
+ return null;
}
- private function addMailProjectMetadata(
+ /* private function addMailProjectMetadata(
PhabricatorLiskDAO $object,
PhabricatorMetaMTAMail $template) {
@@ -2046,37 +2083,38 @@
protected function getMailThreadID(PhabricatorLiskDAO $object) {
return $object->getPHID();
- }
+ }*/
/**
* @task mail
*/
- protected function getStrongestAction(
+ /* protected function getStrongestAction(
PhabricatorLiskDAO $object,
array $xactions) {
return last(msort($xactions, 'getActionStrength'));
- }
+ }*/
/**
* @task mail
*/
- protected function buildReplyHandler(PhabricatorLiskDAO $object) {
+ /* protected function buildReplyHandler(PhabricatorLiskDAO $object) {
throw new Exception('Capability not supported.');
- }
+ }*/
/**
* @task mail
*/
- protected function getMailSubjectPrefix() {
+ /* protected function getMailSubjectPrefix() {
throw new Exception('Capability not supported.');
- }
+ }*/
/**
* @task mail
*/
+ // FIXME: Only needed for feeds now
protected function getMailTags(
PhabricatorLiskDAO $object,
array $xactions) {
@@ -2092,28 +2130,28 @@
/**
* @task mail
*/
- public function getMailTagsMap() {
+ /* public function getMailTagsMap() {
// TODO: We should move shared mail tags, like "comment", here.
return array();
- }
+ }*/
/**
* @task mail
*/
- protected function getMailAction(
+ /* protected function getMailAction(
PhabricatorLiskDAO $object,
array $xactions) {
return $this->getStrongestAction($object, $xactions)->getActionName();
- }
+ }*/
/**
* @task mail
*/
- protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ /* protected function buildMailTemplate(PhabricatorLiskDAO $object) {
throw new Exception('Capability not supported.');
- }
+ }*/
/**
@@ -2187,7 +2225,7 @@
/**
* @task mail
*/
- protected function buildMailBody(
+ /* protected function buildMailBody(
PhabricatorLiskDAO $object,
array $xactions) {
@@ -2234,7 +2272,7 @@
}
return $body;
- }
+ }*/
/* -( Publishing Feed Stories )-------------------------------------------- */
diff --git a/src/applications/transactions/worker/PhabricatorApplicationTransactionEmailWorker.php b/src/applications/transactions/worker/PhabricatorApplicationTransactionEmailWorker.php
new file mode 100644
--- /dev/null
+++ b/src/applications/transactions/worker/PhabricatorApplicationTransactionEmailWorker.php
@@ -0,0 +1,347 @@
+<?php
+
+abstract class PhabricatorApplicationTransactionEmailWorker
+ extends PhabricatorWorker {
+
+ private $actingAsPHID;
+ private $isNewObject;
+ private $heraldHeader;
+ private $excludeMailRecipientPHIDs;
+ private $parentMessageID;
+
+ abstract protected function loadObject($phid);
+ abstract protected function loadXActions($xactions);
+ abstract protected function buildReplyHandler(PhabricatorLiskDAO $object);
+
+ public function getMaximumRetryCount() {
+ return 250;
+ }
+
+ public function getWaitBeforeRetry(PhabricatorWorkerTask $task) {
+ return ($task->getFailureCount() * 15);
+ }
+
+ public function getActingAsPHID() {
+ return $this->actingAsPHID;
+ }
+
+ public function getIsNewObject() {
+ return $this->isNewObject;
+ }
+
+ public function doWork() {
+ $task_data = $this->getTaskData();
+
+ if (!idx($task_data, 'actingAsPHID')) {
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht('Missing actingAsPHID in Tasks Data'));
+ }
+ $this->actingAsPHID = $task_data['actingAsPHID'];
+
+ if (!idx($task_data, 'mailTo')) {
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht('Missing mailTo in Tasks Data'));
+ }
+ $mailTo = $task_data['mailTo'];
+
+ if (!idx($task_data, 'mailCC')) {
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht('Missing mailCC in Tasks Data'));
+ }
+ $mailCC = $task_data['mailCC'];
+
+ $this->heraldHeader = idx($task_data, 'heraldHeader', null);
+
+ $this->isNewObject = idx($task_data, 'isNewObject', false);
+
+ $this->excludeMailRecipientPHIDs = idx($task_data, 'excludeMailRecipientPHIDs');
+
+ $this->parentMessageID = idx($task_data, 'parentMessageID');
+
+ $this->aux_data = idx($task_data, 'aux_data', null);
+
+ $object = $this->loadObject($task_data['object']);
+ if (!$object) {
+ throw new PhabricatorWorkerPermanentFailureException(
+ pht('Unable to load object!'));
+ }
+
+ $xactions = $this->loadXActions($task_data['xactions']);
+ assert_instances_of($xactions, 'PhabricatorApplicationTransaction');
+
+ $email_to = $this->expandPHIDs(array_filter(array_unique($mailTo)));
+ $email_cc = $this->expandPHIDs(array_filter(array_unique($mailCC)));
+ $recipients = array_merge($email_to, $email_cc);
+
+ $users = id(new PhabricatorPeopleQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($recipients)
+ ->execute();
+ $users = mpull($users, null, 'getPHID');
+
+ foreach ($users as $key => $user) {
+ // Check if the receiving user has permissions to view this object
+ if ($object
+ && $object instanceof PhabricatorPolicyInterface
+ && $user
+ && $user instanceof PhabricatorUser) {
+ if (!PhabricatorPolicyFilter::hasCapability(
+ $user,
+ $object,
+ PhabricatorPolicyCapability::CAN_VIEW)) {
+ // User has no permission to this object
+ // so remove them from all lists
+ unset($users[$key]);
+ $phid = array($user->getPHID());
+ $recipients = array_diff($recipients, $phid);
+ $email_to = array_diff($email_to, $phid);
+ $email_cc = array_diff($email_cc, $phid);
+ }
+ }
+ }
+
+ $handles = id(new PhabricatorHandleQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($recipients)
+ ->execute();
+
+ $to_handles = array_select_keys($handles, $email_to);
+ $cc_handles = array_select_keys($handles, $email_cc);
+
+ $emails = array();
+ $send_as_one_email = false;
+ // Render the email for each user individually so correct permissions are preserved
+ foreach ($recipients as $recipient) {
+ $viewer = $users[$recipient];
+
+ $template = $this->buildMailTemplate($object);
+ $template->addPHIDHeaders('X-Phabricator-To', array_keys($email_to));
+ $template->addPHIDHeaders('X-Phabricator-Cc', array_keys($email_cc));
+
+ if (!PhabricatorMetaMTAMail::shouldMultiplexAllMail()) {
+ // If config is set to not multiplex we render as the triggering user
+ $viewer = $users[$this->getActingAsPHID()];
+ $template->addTos($email_to);
+ $template->addCCs($email_cc);
+ $send_as_one_email = true;
+ } else {
+ $template->addTos(array($recipient));
+ }
+
+ // This stuff doesen't change per user. We still handle
+ // it here to support sending in the users locale in the future.
+ $mail_tags = $this->getMailTags($object, $xactions);
+ $action = $this->getMailAction($object, $xactions);
+ $reply_handler = $this->buildReplyHandler($object);
+ $reply_section = $reply_handler->getReplyHandlerInstructions();
+
+ // Render the actual mail body
+ $body = $this->buildMailBody($object, $xactions, $viewer);
+
+ if ($reply_section !== null) {
+ $body->addReplySection($reply_section);
+ }
+
+ $body->addEmailPreferenceSection();
+
+ // FIXME?: This changes the emails a bit (adds a RECIPIENTS header at the bottom)
+ $body->addPlainTextSection('RECIPIENTS', $reply_handler->getRecipientsSummary($to_handles, $cc_handles));
+ $body->addHTMLSection('RECIPIENTS', $reply_handler->getRecipientsSummaryHTML($to_handles, $cc_handles));
+
+ // TODO: Reply-To handling is still missing
+
+ $template
+ ->setFrom($this->getActingAsPHID())
+ ->setSubjectPrefix($this->getMailSubjectPrefix())
+ ->setVarySubjectPrefix('['.$action.']')
+ ->setThreadID($this->getMailThreadID($object), $this->getIsNewObject())
+ ->setRelatedPHID($object->getPHID())
+ ->setExcludeMailRecipientPHIDs($this->excludeMailRecipientPHIDs)
+ ->setMailTags($mail_tags)
+ ->setIsBulk(true)
+ ->setBody($body->render())
+ ->setHTMLBody($body->renderHTML());
+
+ foreach ($body->getAttachments() as $attachment) {
+ $template->addAttachment($attachment);
+ }
+
+ if ($this->heraldHeader) {
+ $template->addHeader('X-Herald-Rules', $this->heraldHeader);
+ }
+
+ if ($object instanceof PhabricatorProjectInterface) {
+ $this->addMailProjectMetadata($object, $template, $viewer);
+ }
+
+ if ($this->parentMessageID) {
+ $template->setParentMessageID($this->parentMessageID);
+ }
+
+ $emails[] = $template;
+
+ if ($send_as_one_email) {
+ // We send all users just a single email
+ break;
+ }
+ }
+
+ foreach ($emails as $mail) {
+ $mail->saveAndSend();
+ }
+
+ return true;
+ }
+
+ protected function expandPHIDs($phids) {
+ // Expand recipients (get projects members)
+ $map = id(new PhabricatorMetaMTAMemberQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPHIDs($phids)
+ ->execute();
+
+ $results = array();
+ foreach ($phids as $phid) {
+ if (isset($map[$phid])) {
+ foreach ($map[$phid] as $expanded_phid) {
+ $results[$expanded_phid] = $expanded_phid;
+ }
+ } else {
+ $results[$phid] = $phid;
+ }
+ }
+ return $results;
+ }
+
+ // FIXME: Make abstract?
+ protected function buildMailTemplate(PhabricatorLiskDAO $object) {
+ throw new Exception('Capability not supported.');
+ }
+
+ // FIXME: Make abstract?
+ protected function getMailSubjectPrefix() {
+ throw new Exception('Capability not supported.');
+ }
+
+ private function addMailProjectMetadata(
+ PhabricatorLiskDAO $object,
+ PhabricatorMetaMTAMail $template,
+ PhabricatorUser $viewer) {
+
+ $project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
+ $object->getPHID(),
+ PhabricatorProjectObjectHasProjectEdgeType::EDGECONST);
+
+ if (!$project_phids) {
+ return;
+ }
+
+ // TODO: This viewer isn't quite right. It would be slightly better to use
+ // the mail recipient, but that's not very easy given the way rendering
+ // works today.
+
+ $handles = id(new PhabricatorHandleQuery())
+ ->setViewer($viewer)
+ ->withPHIDs($project_phids)
+ ->execute();
+
+ $project_tags = array();
+ foreach ($handles as $handle) {
+ if (!$handle->isComplete()) {
+ continue;
+ }
+ $project_tags[] = '<'.$handle->getObjectName().'>';
+ }
+
+ if (!$project_tags) {
+ return;
+ }
+
+ $project_tags = implode(', ', $project_tags);
+ $template->addHeader('X-Phabricator-Projects', $project_tags);
+ }
+
+
+ protected function getMailThreadID(PhabricatorLiskDAO $object) {
+ return $object->getPHID();
+ }
+
+ protected function getMailTags(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ $tags = array();
+
+ foreach ($xactions as $xaction) {
+ $tags[] = $xaction->getMailTags();
+ }
+
+ return array_mergev($tags);
+ }
+
+ public function getMailTagsMap() {
+ // TODO: We should move shared mail tags, like "comment", here.
+ return array();
+ }
+
+ protected function getStrongestAction(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return last(msort($xactions, 'getActionStrength'));
+ }
+
+ protected function getMailAction(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+ return $this->getStrongestAction($object, $xactions)->getActionName();
+ }
+
+ protected function buildMailBody(
+ PhabricatorLiskDAO $object,
+ array $xactions,
+ PhabricatorUser $viewer) {
+
+ $headers = array();
+ $comments = array();
+
+ foreach ($xactions as $xaction) {
+ if ($xaction->shouldHideForMail($xactions)) {
+ continue;
+ }
+
+ $header = $xaction->getTitleForMail();
+ if ($header !== null) {
+ $headers[] = $header;
+ }
+
+ $comment = $xaction->getBodyForMail();
+ if ($comment !== null) {
+ $comments[] = $comment;
+ }
+ }
+
+ $body = new PhabricatorMetaMTAMailBody();
+ $body->setViewer($viewer);
+ $body->addRawSection(implode("\n", $headers));
+
+ foreach ($comments as $comment) {
+ $body->addRemarkupSection($comment);
+ }
+
+ if ($object instanceof PhabricatorCustomFieldInterface) {
+ $field_list = PhabricatorCustomField::getObjectFields(
+ $object,
+ PhabricatorCustomField::ROLE_TRANSACTIONMAIL);
+ $field_list->setViewer($viewer);
+ $field_list->readFieldsFromStorage($object);
+
+ foreach ($field_list->getFields() as $field) {
+ $field->updateTransactionMailBody(
+ $body,
+ $this,
+ $xactions);
+ }
+ }
+
+ return $body;
+ }
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Oct 8, 8:57 PM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
9261068
Default Alt Text
D11329.id27202.diff (26 KB)
Attached To
Mode
D11329: Refactor email rendering into worker tasks
Attached
Detach File
Event Timeline
Log In to Comment