diff --git a/src/IDF/Commit.php b/src/IDF/Commit.php index a0d7c2a..3170c87 100644 --- a/src/IDF/Commit.php +++ b/src/IDF/Commit.php @@ -312,33 +312,42 @@ class IDF_Commit extends Pluf_Model $item->payload = $payload; $item->create(); - if ('' == $conf->getVal('source_notification_email', '')) { - return; - } - $current_locale = Pluf_Translation::getLocale(); - $langs = Pluf::f('languages', array('en')); - Pluf_Translation::loadSetLocale($langs[0]); - $context = new Pluf_Template_Context( - array( - 'c' => $this, - 'project' => $this->get_project(), - 'url_base' => Pluf::f('url_base'), - ) - ); - $tmpl = new Pluf_Template('idf/source/commit-created-email.txt'); - $text_email = $tmpl->render($context); - $addresses = explode(',', $conf->getVal('source_notification_email')); - foreach ($addresses as $address) { - $email = new Pluf_Mail(Pluf::f('from_email'), + $from_email = Pluf::f('from_email'); + $recipients = $project->getNotificationRecipientsForTab('source'); + + foreach ($recipients as $address => $language) { + + if (!empty($this->author) && $this->author->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'commit' => $this, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + // commits are usually not updated, therefor we do not + // distinguish between create and update here + $tplfile = 'idf/source/commit-created-email.txt'; + $subject = __('New commit %s - %s (%s)'); + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, $address, - sprintf(__('New Commit %s - %s (%s)'), + sprintf($subject, $this->scm_id, $this->summary, - $this->get_project()->shortname)); + $project->shortname)); $email->addTextMessage($text_email); $email->sendMail(); } + Pluf_Translation::loadSetLocale($current_locale); } } diff --git a/src/IDF/Issue.php b/src/IDF/Issue.php index 8d1ed34..e1c478a 100644 --- a/src/IDF/Issue.php +++ b/src/IDF/Issue.php @@ -256,91 +256,72 @@ class IDF_Issue extends Pluf_Model */ public function notify($conf, $create=true) { - $prj = $this->get_project(); - $to_email = array(); - if ('' != $conf->getVal('issues_notification_email', '')) { - $langs = Pluf::f('languages', array('en')); - $addresses = explode(',', $conf->getVal('issues_notification_email')); - foreach ($addresses as $address) { - $to_email[] = array($address, $langs[0]); - } - } + $project = $this->get_project(); $current_locale = Pluf_Translation::getLocale(); - $id = '<'.md5($this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; - if ($create) { - if (null != $this->get_owner() and $this->owner != $this->submitter) { - $email_lang = array($this->get_owner()->email, - $this->get_owner()->language); - if (!in_array($email_lang, $to_email)) { - $to_email[] = $email_lang; - } - } - $comments = $this->get_comments_list(array('order' => 'id ASC')); - $context = new Pluf_Template_Context( - array( - 'issue' => $this, - 'comment' => $comments[0], - 'project' => $prj, - 'url_base' => Pluf::f('url_base'), - ) - ); - foreach ($to_email as $email_lang) { - Pluf_Translation::loadSetLocale($email_lang[1]); - $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0], - sprintf(__('Issue %s - %s (%s)'), - $this->id, $this->summary, $prj->shortname)); - $tmpl = new Pluf_Template('idf/issues/issue-created-email.txt'); - $email->addTextMessage($tmpl->render($context)); - $email->addHeaders(array('Message-ID'=>$id)); - $email->sendMail(); - } - } else { - $comments = $this->get_comments_list(array('order' => 'id DESC')); - $email_sender = ''; - if (isset($comments[0])) { - $email_sender = $comments[0]->get_submitter()->email; - } - foreach ($this->get_interested_list() as $interested) { - $email_lang = array($interested->email, - $interested->language); - if (!in_array($email_lang, $to_email)) { - $to_email[] = $email_lang; - } - } - $email_lang = array($this->get_submitter()->email, - $this->get_submitter()->language); - if (!in_array($email_lang, $to_email)) { - $to_email[] = $email_lang; - } - if (null != $this->get_owner()) { - $email_lang = array($this->get_owner()->email, - $this->get_owner()->language); - if (!in_array($email_lang, $to_email)) { - $to_email[] = $email_lang; - } + + $from_email = Pluf::f('from_email'); + $comments = $this->get_comments_list(array('order' => 'id DESC')); + $messageId = '<'.md5('issue'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('issues'); + + // the submitter (might be skipped later on if he is the one who also + // submitted the last comment) + if (!array_key_exists($this->get_submitter()->email, $recipients)) { + $recipients[$this->get_submitter()->email] = $this->get_submitter()->language; + } + + // the owner of the issue, if we have one + $owner = $this->get_owner(); + if (null != $owner && !array_key_exists($owner->email, $recipients)) { + $recipients[$owner->email] = $owner->language; + } + + // additional users who starred the issue + foreach ($this->get_interested_list() as $interested) { + if (array_key_exists($interested->email, $recipients)) + continue; + $recipients[$interested->email] = $interested->language; + } + + foreach ($recipients as $address => $language) { + + // do not notify the creator of the last comment, + // i.e. the user who triggered this notification + if ($comments[0]->get_submitter()->email === $address) { + continue; } - $context = new Pluf_Template_Context( - array( - 'issue' => $this, - 'comments' => $comments, - 'project' => $prj, - 'url_base' => Pluf::f('url_base'), - )); - foreach ($to_email as $email_lang) { - if ($email_lang[0] == $email_sender) { - continue; // Do not notify the one having created - // the comment - } - Pluf_Translation::loadSetLocale($email_lang[1]); - $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0], - sprintf(__('Updated Issue %s - %s (%s)'), - $this->id, $this->summary, $prj->shortname)); - $tmpl = new Pluf_Template('idf/issues/issue-updated-email.txt'); - $email->addTextMessage($tmpl->render($context)); - $email->addHeaders(array('References'=>$id)); - $email->sendMail(); + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'issue' => $this, + 'owns_issue' => $owner !== null && $owner->email === $address, + // the initial comment for create, the last for update + 'comment' => $comments[0], + 'comments' => $comments, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + $tplfile = 'idf/issues/issue-created-email.txt'; + $subject = __('Issue %s - %s (%s)'); + $headers = array('Message-ID' => $messageId); + if (!$create) { + $tplfile = 'idf/issues/issue-updated-email.txt'; + $subject = __('Updated Issue %s - %s (%s)'); + $headers = array('References' => $messageId); } + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, $address, + sprintf($subject, $this->id, $this->summary, $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); } + Pluf_Translation::loadSetLocale($current_locale); } } \ No newline at end of file diff --git a/src/IDF/Project.php b/src/IDF/Project.php index fa63092..ddea3c5 100644 --- a/src/IDF/Project.php +++ b/src/IDF/Project.php @@ -796,4 +796,52 @@ GROUP BY uid"; $this->_isRestricted = false; return false; } + + /** + * Returns an associative array of email addresses to notify about changes + * in a certain tab like 'issues', 'source', and so on. + * + * @param string $tab + * @return array Key is the email address, value is the preferred language setting + */ + public function getNotificationRecipientsForTab($tab) + { + if (!in_array($tab, array('source', 'issues', 'downloads', 'wiki', 'review'))) { + throw new Exception(sprintf('unknown tab %s', $tab)); + } + + $conf = $this->getConf(); + $recipients = array(); + $membership_data = $this->getMembershipData(); + + if ($conf->getVal($tab.'_notification_owners_enabled', false)) { + foreach ($membership_data['owners'] as $owner) { + $recipients[$owner->email] = $owner->language; + } + } + + if ($conf->getVal($tab.'_notification_members_enabled', false)) { + foreach ($membership_data['members'] as $member) { + $recipients[$member->email] = $member->language; + } + } + + if ($conf->getVal($tab.'_notification_email_enabled', false)) { + $addresses = preg_split('/\s*,\s*/', + $conf->getVal($tab.'_notification_email', ''), + -1, PREG_SPLIT_NO_EMPTY); + + // we use a default language setting for this plain list of + // addresses, but we ensure that we do not overwrite an existing + // address which might come with a proper setting already + $languages = Pluf::f('languages', array('en')); + foreach ($addresses as $address) { + if (array_key_exists($address, $recipients)) + continue; + $recipients[$address] = $languages[0]; + } + } + + return $recipients; + } } diff --git a/src/IDF/Review/Comment.php b/src/IDF/Review/Comment.php index 762973d..1e07222 100644 --- a/src/IDF/Review/Comment.php +++ b/src/IDF/Review/Comment.php @@ -175,50 +175,63 @@ class IDF_Review_Comment extends Pluf_Model */ public function notify($conf, $create=true) { - $patch = $this->get_patch(); - $review = $patch->get_review(); - $prj = $review->get_project(); - $to_email = array(); - if ('' != $conf->getVal('review_notification_email', '')) { - $langs = Pluf::f('languages', array('en')); - $to_email[] = array($conf->getVal('issues_notification_email'), - $langs[0]); - } - $current_locale = Pluf_Translation::getLocale(); - $reviewers = $review->getReviewers(); + $patch = $this->get_patch(); + $review = $patch->get_review(); + $prj = $review->get_project(); + $reviewers = $review->getReviewers(); + if (!Pluf_Model_InArray($review->get_submitter(), $reviewers)) { $reviewers[] = $review->get_submitter(); } + $comments = $patch->getFileComments(array('order' => 'id DESC')); $gcomments = $patch->get_comments_list(array('order' => 'id DESC')); - $context = new Pluf_Template_Context( - array( - 'review' => $review, - 'patch' => $patch, - 'comments' => $comments, - 'gcomments' => $gcomments, - 'project' => $prj, - 'url_base' => Pluf::f('url_base'), - ) - ); - // build the list of emails and lang + + $recipients = $prj->getNotificationRecipientsForTab('review'); + foreach ($reviewers as $user) { - $email_lang = array($user->email, - $user->language); - if (!in_array($email_lang, $to_email)) { - $to_email[] = $email_lang; - } + if (array_key_exists($user->email, $recipients)) + continue; + $recipients[$user->email] = $user->language; } - $tmpl = new Pluf_Template('idf/review/review-updated-email.txt'); - foreach ($to_email as $email_lang) { - Pluf_Translation::loadSetLocale($email_lang[1]); - $email = new Pluf_Mail(Pluf::f('from_email'), $email_lang[0], - sprintf(__('Updated Code Review %s - %s (%s)'), - $review->id, $review->summary, $prj->shortname)); - - $email->addTextMessage($tmpl->render($context)); + + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('review'.$review->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + + foreach ($recipients as $address => $language) { + + if ($this->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'review' => $review, + 'patch' => $patch, + 'comments' => $comments, + 'gcomments' => $gcomments, + 'project' => $prj, + 'url_base' => Pluf::f('url_base'), + )); + + // reviews only updated through comments, see IDF_Review_Patch::notify() + $tplfile = 'idf/review/review-updated-email.txt'; + $subject = __('Updated Code Review %s - %s (%s)'); + $headers = array('References' => $messageId); + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, $address, + sprintf($subject, $review->id, $review->summary, $prj->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); $email->sendMail(); } + Pluf_Translation::loadSetLocale($current_locale); } diff --git a/src/IDF/Review/Patch.php b/src/IDF/Review/Patch.php index a98f49d..a8342bd 100644 --- a/src/IDF/Review/Patch.php +++ b/src/IDF/Review/Patch.php @@ -42,9 +42,9 @@ class IDF_Review_Patch extends Pluf_Model 'id' => array( 'type' => 'Pluf_DB_Field_Sequence', - 'blank' => true, + 'blank' => true, ), - 'review' => + 'review' => array( 'type' => 'Pluf_DB_Field_Foreignkey', 'model' => 'IDF_Review', @@ -59,7 +59,7 @@ class IDF_Review_Patch extends Pluf_Model 'size' => 250, 'verbose' => __('summary'), ), - 'commit' => + 'commit' => array( 'type' => 'Pluf_DB_Field_Foreignkey', 'model' => 'IDF_Commit', @@ -129,8 +129,8 @@ class IDF_Review_Patch extends Pluf_Model function postSave($create=false) { if ($create) { - IDF_Timeline::insert($this, - $this->get_review()->get_project(), + IDF_Timeline::insert($this, + $this->get_review()->get_project(), $this->get_review()->get_submitter()); IDF_Search::index($this->get_review()); } @@ -139,7 +139,7 @@ class IDF_Review_Patch extends Pluf_Model public function timelineFragment($request) { $review = $this->get_review(); - $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', array($request->project->shortname, $review->id)); $out = '