1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-26 08:42:41 +01:00

Send Differential e-mails in user's language

Summary:
Works this way:

- Select users' language with multiplexing.
- Select default language otherwise (it can be different from current user's language).
- Build body and subject for each user individually.
- Set the original language after sending the mails.

Test Plan:
- Comment on a diff of user with custom translation.
- Set default to a custom translation. Comment on a diff of user with default translation.
- Set default to a default translation. Comment on a diff of user with default translation.

Repeat with/without multiplexing.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Maniphest Tasks: T1139

Differential Revision: https://secure.phabricator.com/D2774
This commit is contained in:
vrana 2012-06-15 23:21:25 -07:00
parent 112acf11cf
commit e84f9f9ec9
7 changed files with 165 additions and 57 deletions

View file

@ -62,9 +62,7 @@ abstract class PhabricatorController extends AphrontController {
$translation = $user->getTranslation();
if ($translation &&
$translation != PhabricatorEnv::getEnvConfig('translation.provider') &&
class_exists($translation) &&
is_subclass_of($translation, 'PhabricatorTranslation')) {
$translation != PhabricatorEnv::getEnvConfig('translation.provider')) {
$translation = newv($translation, array());
PhutilTranslator::getInstance()
->setLanguage($translation->getLanguage())

View file

@ -20,6 +20,9 @@ final class DifferentialCommentMail extends DifferentialMail {
protected $changedByCommit;
private $addedReviewers;
private $addedCCs;
public function setChangedByCommit($changed_by_commit) {
$this->changedByCommit = $changed_by_commit;
return $this;
@ -87,20 +90,11 @@ final class DifferentialCommentMail extends DifferentialMail {
return $verb;
}
protected function renderBody() {
$comment = $this->getComment();
$actor = $this->getActorName();
$name = $this->getRevision()->getTitle();
$verb = $this->getVerb();
$body = array();
$body[] = "{$actor} has {$verb} the revision \"{$name}\".";
protected function prepareBody() {
parent::prepareBody();
// If the commented added reviewers or CCs, list them explicitly.
$meta = $comment->getMetadata();
$meta = $this->getComment()->getMetadata();
$m_reviewers = idx(
$meta,
DifferentialComment::METADATA_ADDED_REVIEWERS,
@ -113,16 +107,32 @@ final class DifferentialCommentMail extends DifferentialMail {
if ($load) {
$handles = id(new PhabricatorObjectHandleData($load))->loadHandles();
if ($m_reviewers) {
$body[] = 'Added Reviewers: '.$this->renderHandleList(
$handles,
$m_reviewers);
$this->addedReviewers = $this->renderHandleList($handles, $m_reviewers);
}
if ($m_cc) {
$body[] = 'Added CCs: '.$this->renderHandleList(
$handles,
$m_cc);
$this->addedCCs = $this->renderHandleList($handles, $m_cc);
}
}
}
protected function renderBody() {
$comment = $this->getComment();
$actor = $this->getActorName();
$name = $this->getRevision()->getTitle();
$verb = $this->getVerb();
$body = array();
$body[] = "{$actor} has {$verb} the revision \"{$name}\".";
if ($this->addedReviewers) {
$body[] = 'Added Reviewers: '.$this->addedReviewers;
}
if ($this->addedCCs) {
$body[] = 'Added CCs: '.$this->addedCCs;
}
$body[] = null;

View file

@ -78,7 +78,6 @@ abstract class DifferentialMail {
}
$cc_phids = $this->getCCPHIDs();
$body = $this->buildBody();
$attachments = $this->buildAttachments();
$template = new PhabricatorMetaMTAMail();
@ -90,10 +89,6 @@ abstract class DifferentialMail {
}
$template
->setSubject($this->renderSubject())
->setSubjectPrefix($this->getSubjectPrefix())
->setVarySubjectPrefix($this->renderVaryPrefix())
->setBody($body)
->setIsHTML($this->shouldMarkMailAsHTML())
->setParentMessageID($this->parentMessageID)
->addHeader('Thread-Topic', $this->getThreadTopic());
@ -172,25 +167,62 @@ abstract class DifferentialMail {
$phids = array_keys($phids);
$handles = id(new PhabricatorObjectHandleData($phids))->loadHandles();
$objects = id(new PhabricatorObjectHandleData($phids))->loadObjects();
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL,
array(
'mail' => $template,
)
);
PhutilEventEngine::dispatchEvent($event);
$to_handles = array_select_keys($handles, $to_phids);
$cc_handles = array_select_keys($handles, $cc_phids);
$template = $event->getValue('mail');
$this->prepareBody();
$mails = $reply_handler->multiplexMail(
$template,
array_select_keys($handles, $to_phids),
array_select_keys($handles, $cc_phids));
$mails = $reply_handler->multiplexMail($template, $to_handles, $cc_handles);
foreach ($mails as $mail) {
$mail->saveAndSend();
$original_translator = PhutilTranslator::getInstance();
if (!PhabricatorMetaMTAMail::shouldMultiplexAllMail()) {
$translation = PhabricatorEnv::newObjectFromConfig(
'translation.provider');
$translator = id(new PhutilTranslator())
->setLanguage($translation->getLanguage())
->addTranslations($translation->getTranslations());
}
try {
foreach ($mails as $mail) {
if (PhabricatorMetaMTAMail::shouldMultiplexAllMail()) {
$translation = newv($mail->getTranslation($objects), array());
$translator = id(new PhutilTranslator())
->setLanguage($translation->getLanguage())
->addTranslations($translation->getTranslations());
PhutilTranslator::setInstance($translator);
}
$body =
$this->buildBody()."\n".
$reply_handler->getRecipientsSummary($to_handles, $cc_handles);
$mail
->setSubject($this->renderSubject())
->setSubjectPrefix($this->getSubjectPrefix())
->setVarySubjectPrefix($this->renderVaryPrefix())
->setBody($body);
$event = new PhabricatorEvent(
PhabricatorEventType::TYPE_DIFFERENTIAL_WILLSENDMAIL,
array(
'mail' => $mail,
)
);
PhutilEventEngine::dispatchEvent($event);
$mail = $event->getValue('mail');
$mail->saveAndSend();
}
} catch (Exception $ex) {
PhutilTranslator::setInstance($original_translator);
throw $ex;
}
PhutilTranslator::setInstance($original_translator);
}
protected function getMailTags() {
@ -205,6 +237,17 @@ abstract class DifferentialMail {
return false;
}
/**
* @{method:buildBody} is called once for each e-mail recipient to allow
* translating text to his language. This method can be used to load data that
* don't need translation and use them later in @{method:buildBody}.
*
* @param
* @return
*/
protected function prepareBody() {
}
protected function buildBody() {
$body = $this->renderBody();
@ -369,6 +412,8 @@ EOTEXT;
$body = array();
foreach ($aux_fields as $field) {
$field->setRevision($this->getRevision());
// TODO: Introduce and use getRequiredHandlePHIDsForMail() and load all
// handles in prepareBody().
$text = $field->renderValueForMail($phase);
if ($text !== null) {
$body[] = $text;

View file

@ -20,6 +20,8 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
protected $comments;
private $patch;
public function setComments($comments) {
$this->comments = $comments;
return $this;
@ -40,6 +42,19 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
$this->setChangesets($changesets);
}
protected function prepareBody() {
parent::prepareBody();
$inline_max_length = PhabricatorEnv::getEnvConfig(
'metamta.differential.inline-patches');
if ($inline_max_length) {
$patch = $this->buildPatch();
if (count(explode("\n", $patch)) <= $inline_max_length) {
$this->patch = $patch;
}
}
}
protected function renderReviewRequestBody() {
$revision = $this->getRevision();
@ -65,14 +80,9 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
$body[] = null;
}
$inline_key = 'metamta.differential.inline-patches';
$inline_max_length = PhabricatorEnv::getEnvConfig($inline_key);
if ($inline_max_length) {
$patch = $this->buildPatch();
if (count(explode("\n", $patch)) <= $inline_max_length) {
$body[] = 'CHANGE DETAILS';
$body[] = $patch;
}
if ($this->patch) {
$body[] = 'CHANGE DETAILS';
$body[] = $this->patch;
}
return implode("\n", $body);
@ -110,14 +120,9 @@ abstract class DifferentialReviewRequestMail extends DifferentialMail {
}
private function buildPatch() {
$revision = $this->getRevision();
$revision_id = $revision->getID();
$diff = new DifferentialDiff();
$diffs = $revision->loadDiffs();
$diff_number = count($diffs);
$diff = array_pop($diffs);
$diff->attachChangesets($diff->loadChangesets());
$diff->attachChangesets($this->getChangesets());
// TODO: We could batch this to improve performance.
foreach ($diff->getChangesets() as $changeset) {
$changeset->attachHunks($changeset->loadHunks());

View file

@ -71,6 +71,22 @@ abstract class PhabricatorMailReplyHandler {
return null;
}
final public function getRecipientsSummary(
array $to_handles,
array $cc_handles) {
assert_instances_of($to_handles, 'PhabricatorObjectHandle');
assert_instances_of($cc_handles, 'PhabricatorObjectHandle');
$body = '';
if ($to_handles) {
$body .= "To: ".implode(', ', mpull($to_handles, 'getName'))."\n";
}
if ($cc_handles) {
$body .= "Cc: ".implode(', ', mpull($cc_handles, 'getName'))."\n";
}
return $body;
}
final public function multiplexMail(
PhabricatorMetaMTAMail $mail_template,
array $to_handles,
@ -115,13 +131,12 @@ abstract class PhabricatorMailReplyHandler {
$body = $mail_template->getBody();
$body .= "\n";
if ($to_handles) {
$body .= "To: ".implode(', ', mpull($to_handles, 'getName'))."\n";
$add_headers['X-Phabricator-To'] = $this->formatPHIDList($to_handles);
}
if ($cc_handles) {
$body .= "Cc: ".implode(', ', mpull($cc_handles, 'getName'))."\n";
$add_headers['X-Phabricator-Cc'] = $this->formatPHIDList($cc_handles);
}
$body .= $this->getRecipientsSummary($to_handles, $cc_handles);
foreach ($recipients as $recipient) {
$mail = clone $mail_template;

View file

@ -119,6 +119,28 @@ final class PhabricatorMetaMTAMail extends PhabricatorMetaMTADAO {
return $this;
}
public function getTranslation(array $objects) {
$default_translation = PhabricatorEnv::getEnvConfig('translation.provider');
$return = null;
$recipients = array_merge(
idx($this->parameters, 'to', array()),
idx($this->parameters, 'cc', array()));
foreach (array_select_keys($objects, $recipients) as $object) {
$translation = null;
if ($object instanceof PhabricatorUser) {
$translation = $object->getTranslation();
}
if (!$translation) {
$translation = $default_translation;
}
if ($return && $translation != $return) {
return $default_translation;
}
$return = $translation;
}
return $return;
}
public function addHeader($name, $value) {
$this->parameters['headers'][$name] = $value;
return $this;

View file

@ -96,6 +96,19 @@ final class PhabricatorUser extends PhabricatorUserDAO implements PhutilPerson {
return $this->sex;
}
public function getTranslation() {
try {
if ($this->translation &&
class_exists($this->translation) &&
is_subclass_of($this->translation, 'PhabricatorTranslation')) {
return $this->translation;
}
} catch (PhutilMissingSymbolException $ex) {
return null;
}
return null;
}
public function isLoggedIn() {
return !($this->getPHID() === null);
}