Index: mail.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/mail.inc,v retrieving revision 1.105 diff -u -r1.105 mail.inc --- mail.inc 7 Mar 2008 21:30:23 -0000 1.105 +++ mail.inc 2 May 2008 07:09:57 -0000 @@ -1,6 +1,6 @@ type == 'project') { @@ -173,7 +173,7 @@ } } -function project_mail_notify($nid) { +function project_mail_notify($nid, $ops = array('notify')) { global $base_url, $user; if (defined('PROJECT_NOMAIL')) { @@ -189,40 +189,7 @@ // Store a copy of the issue, so we can load the original issue values // below. $issue = drupal_clone($node); - - // Load in the original issue data here, since we want a running - // reverse history. - $original_issue_data = unserialize($node->original_issue_data); - foreach ($fields as $field => $label) { - if ($field != 'name' && $field != 'updator') { - $issue->$field = $original_issue_data->$field; - } - } - - // Record users that are connected to this issue. - $uids = array(); - if ($node->assigned) { - $uids[$node->assigned] = $node->assigned; - } - - // Create complete history of the bug report. $history = array($issue); - $result = db_query('SELECT u.name, c.cid, c.nid, c.subject, c.comment, c.uid, c.format, pic.* FROM {project_issue_comments} pic INNER JOIN {comments} c ON c.cid = pic.cid INNER JOIN {users} u ON u.uid = c.uid WHERE c.nid = %d AND c.status = %d ORDER BY pic.timestamp', $node->nid, COMMENT_PUBLISHED); - - while ($comment = db_fetch_object($result)) { - $comment->comment = db_decode_blob($comment->comment); - $comment->files = _comment_upload_load_files($comment->cid); - $history[] = $comment; - // Record users that are connected to this issue. - if ($comment->uid) { - $uids[$comment->uid] = $comment->uid; - } - // We need the most recent cid and the next most recent cid for the - // message headers. Instead of issuing another query, just keep track - // of them here. - $previous_cid = isset($cid) ? $cid : ''; - $cid = $comment->cid; - } // Create mail header $sender->name = mime_header_encode(t('!name (!site)', array('!name' => $user->name, '!site' => variable_get('site_name', 'Drupal')))); @@ -255,51 +222,88 @@ $header['Message-Id'] = "nid&host=@$domain>"; } - if (count($uids)) { - $placeholders = implode(',', array_fill(0, count($uids), '%d')); - array_unshift($uids, $node->pid); - $result = db_query("SELECT p.*, u.uid, u.name, u.mail FROM {project_subscriptions} p INNER JOIN {users} u ON p.uid = u.uid WHERE u.status = 1 AND p.nid = %d AND (p.level = 2 OR (p.level = 1 AND u.uid IN ($placeholders)))", $uids); - } - else { - $result = db_query('SELECT p.*, u.uid, u.name, u.mail FROM {project_subscriptions} p INNER JOIN {users} u ON p.uid = u.uid WHERE u.status = 1 AND p.nid = %d AND p.level = 2', $node->pid); - } - - // Create link to related node - $links = t('Issue status update for !link', array('!link' => "\n". url("node/$node->nid", NULL, NULL, 1))) ."\n"; - $links .= t('Post a follow up: !link', array('!link' => "\n". url("comment/reply/$node->nid", NULL, 'comment-form', 1))) ."\n"; - - // To save workload, check here if either the anonymous role or the - // authenticated role has the 'view uploaded files' permission, since - // we only need to process each user's file access permission if this - // is NOT the case. - $check_file_perms = !db_num_rows(db_query("SELECT rid FROM {permission} WHERE perm LIKE '%view uploaded files%' AND rid IN (%d, %d)", DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID)); - project_mail_output($node->title, 0); - $subject = t('[!short_name] [!category] !title', array('!short_name' => $project->uri, '!category' => $node->category, '!title' => $node->title)); - while ($recipient = db_fetch_object($result)) { - if ($check_file_perms) { - $account = user_load(array('uid' => $recipient->uid)); - $display_files = user_access('view uploaded files', $account); + // Having set up the elements common to all the emails, we now dispatch + // emails according to the array of $ops that were passed in. + if (($op = array_search('assign_update', $ops)) || ($op = array_search('assign_insert', $ops))) { + $assignee = user_load($node->assigned); + $links = t('!user has assigned an issue to you in the !short_name issue queue: !link', array('!user' => $user->name, '!short_name' => $project->uri, '!link' => "\n". url("node/$node->nid", NULL, NULL, 1))) ."\n"; + $links .= t('Post a follow up: !link', array('!link' => "\n". url("comment/reply/$node->nid", NULL, 'comment-form', 1))) ."\n"; + + $subject = t('[!short_name - Issue Assigned] [!category] !title', array('!short_name' => $project->uri, '!category' => $node->category, '!title' => $node->title)); + $body = "$links\n". project_mail_generate_followup_mail_body($node, $history, FALSE, $op); + drupal_mail('project_issue_update', $assignee->mail, $subject, $body, $from, $header); + } + if (in_array('notify', $ops)) { + // Create link to related node + $links = t('Issue status update for !link', array('!link' => "\n". url("node/$node->nid", NULL, NULL, 1))) ."\n"; + $links .= t('Post a follow up: !link', array('!link' => "\n". url("comment/reply/$node->nid", NULL, 'comment-form', 1))) ."\n"; + + // To save workload, check here if either the anonymous role or the + // authenticated role has the 'view uploaded files' permission, since + // we only need to process each user's file access permission if this + // is NOT the case. + $check_file_perms = !db_num_rows(db_query("SELECT rid FROM {permission} WHERE perm LIKE '%view uploaded files%' AND rid IN (%d, %d)", DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID)); + + // Record users that are connected to this issue. + $uids = array(); + if ($node->assigned) { + $uids[$node->assigned] = $node->assigned; + } + + // Create complete history of the bug report. + $result = db_query('SELECT u.name, c.cid, c.nid, c.subject, c.comment, c.uid, c.format, pic.* FROM {project_issue_comments} pic INNER JOIN {comments} c ON c.cid = pic.cid INNER JOIN {users} u ON u.uid = c.uid WHERE c.nid = %d AND c.status = %d ORDER BY pic.timestamp', $node->nid, COMMENT_PUBLISHED); + while ($comment = db_fetch_object($result)) { + $comment->comment = db_decode_blob($comment->comment); + $comment->files = _comment_upload_load_files($comment->cid); + $history[] = $comment; + // Record users that are connected to this issue. + if ($comment->uid) { + $uids[$comment->uid] = $comment->uid; + } + // We need the most recent cid and the next most recent cid for the + // message headers. Instead of issuing another query, just keep track + // of them here. + $previous_cid = isset($cid) ? $cid : ''; + $cid = $comment->cid; + } + + $subject = t('[!short_name] [!category] !title', array('!short_name' => $project->uri, '!category' => $node->category, '!title' => $node->title)); + + if (count($uids)) { + $placeholders = implode(',', array_fill(0, count($uids), '%d')); + array_unshift($uids, $node->pid); + $result = db_query("SELECT p.*, u.uid, u.name, u.mail FROM {project_subscriptions} p INNER JOIN {users} u ON p.uid = u.uid WHERE u.status = 1 AND p.nid = %d AND (p.level = 2 OR (p.level = 1 AND u.uid IN ($placeholders)))", $uids); } else { - $display_files = TRUE; + $result = db_query('SELECT p.*, u.uid, u.name, u.mail FROM {project_subscriptions} p INNER JOIN {users} u ON p.uid = u.uid WHERE u.status = 1 AND p.nid = %d AND p.level = 2', $node->pid); + } + + while ($recipient = db_fetch_object($result)) { + if ($check_file_perms) { + $account = user_load(array('uid' => $recipient->uid)); + $display_files = user_access('view uploaded files', $account); + } + else { + $display_files = TRUE; + } + $body = "$links\n". project_mail_generate_followup_mail_body($node, $history, $display_files); + drupal_mail('project_issue_update', $recipient->mail, $subject, $body, $from, $header); + } + + if (is_array($project->mail_copy_filter) && count(array_filter($project->mail_copy_filter)) && !$project->mail_copy_filter[$node->category]) { + return; + } + + if (is_array($project->mail_copy_filter_state) && count(array_filter($project->mail_copy_filter_state)) && !$project->mail_copy_filter_state[$node->sid]) { + return; + } + + if ($project->mail_copy) { + $body = "$links\n". project_mail_generate_followup_mail_body($node, $history, TRUE); + drupal_mail('project_issue_update', $project->mail_copy, $subject, $body, $from, $header); } - $body = "$links\n". project_mail_generate_followup_mail_body($node, $history, $display_files); - drupal_mail('project_issue_update', $recipient->mail, $subject, $body, $from, $header); - } - - if (is_array($project->mail_copy_filter) && count(array_filter($project->mail_copy_filter)) && !$project->mail_copy_filter[$node->category]) { - return; - } - - if (is_array($project->mail_copy_filter_state) && count(array_filter($project->mail_copy_filter_state)) && !$project->mail_copy_filter_state[$node->sid]) { - return; - } - - if ($project->mail_copy) { - $body = "$links\n". project_mail_generate_followup_mail_body($node, $history, TRUE); - drupal_mail('project_issue_update', $project->mail_copy, $subject, $body, $from, $header); } } @@ -312,22 +316,24 @@ * An array containing the history of issue followups. * @param $display_files * Boolean indicating if file attachments should be displayed. + * @param $op + * A string indicating the type of message body to be generated. * @return * A string of the email body. */ -function project_mail_generate_followup_mail_body($node, $history, $display_files) { +function project_mail_generate_followup_mail_body($node, $history, $display_files, $op = 'notify') { global $user; - static $output_with_files = NULL, $output_without_files = NULL; + static $output_with_files = array(), $output_without_files = array(); // Return cached output if available. if ($display_files) { - if (isset($output_with_files)) { - return $output_with_files; + if (isset($output_with_files[$op])) { + return $output_with_files[$op]; } } else { - if (isset($output_without_files)) { - return $output_without_files; + if (isset($output_without_files[$op])) { + return $output_without_files[$op]; } } @@ -370,7 +376,7 @@ $hr = str_repeat('-', 72); - if (count($history)) { + if (count($history) && $op == 'notify') { $body .= "\n\n"; $body .= t('Original issue:') ."\n"; @@ -382,15 +388,16 @@ } } } - - $output = "$summary\n$body"; + + $assignee_text = "\n" . t("The text of your co-maintainer's comment where s/he assigned this issue to you is below.") . "\n" . $hr; + $output = $op == 'notify' ? "$summary\n$body" : "$assignee_text\n\n$summary\n$body"; // Set cached output. if ($display_files) { - $output_with_files = $output; + $output_with_files[$op] = $output; } else { - $output_without_files = $output; + $output_without_files[$op] = $output; } return $output; Index: issue.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/issue.inc,v retrieving revision 1.304.2.6 diff -u -r1.304.2.6 issue.inc --- issue.inc 14 Apr 2008 00:27:24 -0000 1.304.2.6 +++ issue.inc 2 May 2008 07:09:57 -0000 @@ -1,6 +1,6 @@ empty($node->assigned) ? t('Unassigned') : t('Unassign')) + $assigned; } @@ -797,6 +798,10 @@ '#default_value' => $node->assigned, '#options' => $assigned, ); + $form['issue_info']['originally_assigned'] = array( + '#type' => 'hidden', + '#value' => $node->assigned, + ); if (count($states) > 1) { $form['issue_info']['sid'] = array( '#type' => 'select', @@ -1004,6 +1009,15 @@ } // Always let the person replying assign it to themselves. $assigned[$user->uid] = $user->name; + + // If the current user is one of the project maintainers, allow them to select + // from a list of all the project maintainers when assigning the issue. + if (db_result(db_query("SELECT nid FROM {cvs_project_maintainers} WHERE uid = %d AND nid = %d", $user->uid, $node->nid))) { + $result = db_query("SELECT m.uid, u.name FROM {cvs_project_maintainers} m INNER JOIN {users} u ON m.uid = u.uid WHERE m.uid != 0 AND m.nid = %d", $node->nid); + while ($row = db_fetch_array($result)) { + $assigned = array_flip(array_merge(array_flip($assigned), array($row['name'] => $row['uid']))); // these array acrobatics ensure that we have no duplicate values being added + } + } } } @@ -2066,7 +2080,7 @@ ); $sql[] = '('. implode(' OR ', $_sql) .')'; break; - case 'assigned': + case 'assigned': // TODO I think this is where the change would need to be made $sql[] = project_issue_query_sql_field('p.assigned', $value, 0, ' OR ', 'project_issue_query_user'); break; case 'submitted': Index: project_issue.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/project_issue.module,v retrieving revision 1.88.2.2 diff -u -r1.88.2.2 project_issue.module --- project_issue.module 13 Apr 2008 20:13:12 -0000 1.88.2.2 +++ project_issue.module 2 May 2008 07:09:57 -0000 @@ -1,6 +1,6 @@ project_issues // issue comments -> project_issue_comments @@ -794,7 +794,7 @@ * If $nid is not passed, an associative array of nids that are marked for * notification emails, with the following structure: key = nid, value = nid. */ -function project_issue_set_mail_notify($nid = NULL) { +function project_issue_set_mail_notify($nid = NULL, $op = 'notify') { static $nids = array(); if (!isset($nid)) { @@ -803,7 +803,7 @@ return $return; } else { - $nids[$nid] = $nid; + $nids[$nid][$op] = $op; } } @@ -819,8 +819,8 @@ // loaded. Since the cached pages won't have any new mail notifications, // we can safely test for this case. if (!empty($nids)) { - foreach ($nids as $nid) { - project_mail_notify($nid); + foreach ($nids as $nid => $ops) { + project_mail_notify($nid, $ops); } } } Index: comment.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/project_issue/comment.inc,v retrieving revision 1.129.2.2 diff -u -r1.129.2.2 comment.inc --- comment.inc 14 Apr 2008 00:26:24 -0000 1.129.2.2 +++ comment.inc 2 May 2008 07:09:57 -0000 @@ -1,6 +1,6 @@ assigned && $comment_data->assigned != $user->uid && $comment_data->assigned != $comment_data->originally_assigned) { + // Only way we get here is if the issue isn't (being) unassigned, and it's being assigned + // to someone who's NOT the current user, and who it wasn't originally assigned to. In other words + // we only get here if one maintainer is assigning it to another maintainer. + project_issue_set_mail_notify($comment_data->nid, "assign_$op"); + } // In order to deal with deleted/unpublished comments, make sure that we're performing // the updates to the issue with the latest available published comment.