diff --git a/includes/mail.inc b/includes/mail.inc index e6bf651..002754c 100644 --- a/includes/mail.inc +++ b/includes/mail.inc @@ -268,15 +268,21 @@ function project_issue_mail_notify($nid) { // Initialize the recipient list. After compilation, the list will include // users that are: - // - globally subscribed to all issues - // - globally subscribed to "own" issues // - subscribed to all issues of the project // - subscribed to "own" issues of the project + // - subscribed to all issues by default (global default) + // - subscribed to "own" issues by default (global default) + // Note that "own" changes meaning depending on if flag.module is enabled // and configured for following issues. $recipients = array(); - $args = array(); + // In both queries, the first placeholder is always the node ID of the + // project that the current issue belongs to, since we need to restrict to + // that project for the per-project settings, and LEFT JOIN on that project + // to catch all the users with a default notification setting (everyone who + // doesn't have a specific preference for that project). + $args = array($node->project_issue['pid']); // Build up filters for different issue notification levels. $filter_array = array(); @@ -290,24 +296,24 @@ function project_issue_mail_notify($nid) { } $filter = implode(" OR ", $filter_array); - // Pull users that want global notifications. - $global_notification_query = "SELECT pi.uid, u.name, u.mail - FROM {project_issue_notification_global} pi + // Pull users that want notifications at the project level. + $project_notification_query = "SELECT pi.uid, u.name, u.mail + FROM {project_issue_notification_project} pi INNER JOIN {users} u ON pi.uid = u.uid - WHERE u.status = 1 AND (" . $filter . ")"; - $result = db_query($global_notification_query, $args); + WHERE u.status = 1 AND pi.nid = %d AND (" . $filter . ")"; + $result = db_query($project_notification_query, $args); while ($account = db_fetch_object($result)) { $recipients[$account->uid] = $account; } - // Pull users that want notifications at the project level. - $project_notification_query = "SELECT pi.uid, u.name, u.mail - FROM {project_issue_notification_project} pi + // Pull users that want global notifications if they haven't defined a + // per-project setting for this project. + $default_notification_query = "SELECT pi.uid, u.name, u.mail + FROM {project_issue_notification_global} pi + LEFT JOIN {project_issue_notification_project} pinp ON pi.uid = pinp.uid AND pinp.nid = %d INNER JOIN {users} u ON pi.uid = u.uid - WHERE u.status = 1 AND pi.nid = %d AND (" . $filter . ")"; - $project_notification_args = $args; - array_unshift($project_notification_args, $node->project_issue['pid']); - $result = db_query($project_notification_query, $project_notification_args); + WHERE u.status = 1 AND pinp.level IS NULL AND (" . $filter . ")"; + $result = db_query($default_notification_query, $args); while ($account = db_fetch_object($result)) { $recipients[$account->uid] = $account; } diff --git a/includes/notification.inc b/includes/notification.inc index 4dce153..224f7b5 100644 --- a/includes/notification.inc +++ b/includes/notification.inc @@ -43,19 +43,7 @@ function project_issue_notification_user_form(&$form_state, $account) { '#collapsible' => TRUE, ); - $form['project_issue_notification']['level'] = array( - '#type' => 'radios', - '#title' => t('E-mail notification for all projects'), - '#options' => $options, - '#default_value' => $account->project_issue_notification['level'], - // TODO: this could probably use some description text. - ); - - // Per-project notification level (only enabled). - // We only allow to change (and remove) per-project notifications on this - // form. Users are able to subscribe to further projects by visiting the - // individual project pages. In terms of UX, that's preferred anyway, since - // a user normally wants to know and be sure what exactly she subscribes to. + // Per-project notification levels. $form['project_issue_notification']['projects'] = array( '#theme' => 'project_issue_notification_projects_table', '#header' => array(t('Project'), t('Notification level')), @@ -80,6 +68,35 @@ function project_issue_notification_user_form(&$form_state, $account) { ); } + $form['project_issue_notification']['projects']['new']['title'] = array( + '#type' => 'textfield', + '#size' => 30, + '#autocomplete_path' => 'project/autocomplete/project', + ); + $form['project_issue_notification']['projects']['new']['level'] = array( + '#type' => 'select', + '#options' => $options, + '#default_value' => $account->project_issue_notification['level'], + ); + + $form['project_issue_notification']['projects']['default']['title'] = array( + '#value' => t('Default for all other projects'), + ); + $form['project_issue_notification']['projects']['default']['level'] = array( + '#type' => 'select', + '#options' => $options, + '#default_value' => $account->project_issue_notification['level'], + ); + $form['project_issue_notification']['projects']['default']['title'] = array( + '#value' => t('Default for all other projects'), + ); + $form['project_issue_notification']['projects']['default']['level'] = array( + '#type' => 'select', + '#options' => $options, + '#default_value' => $account->project_issue_notification['level'], + '#parents' => array('project_issue_notification', 'projects', 'default'), + ); + $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Save'), @@ -89,15 +106,47 @@ function project_issue_notification_user_form(&$form_state, $account) { } /** + * Form validation handler for project_issue_notification_user_form(). + * + * If the user is trying to add notification preferences for a new project, we + * validate the project title. If we can't find the project, we set a form + * error. If we find the project, we save the nid into $form_state so we can + * use that in the submit handler. + */ +function project_issue_notification_user_form_validate($form, &$form_state) { + if (!empty($form_state['values']['project_issue_notification']['projects']['new']['title'])) { + $nid = db_result(db_query("SELECT nid FROM {node} WHERE title = '%s' AND type = '%s'", $form_state['values']['project_issue_notification']['projects']['new']['title'], 'project_project')); + if (empty($nid)) { + form_set_error('project_issue_notification][projects][new][title', t('The name you entered (%title) is not a valid project.', array('%title' => $form_state['values']['project_issue_notification']['projects']['new']['title']))); + } + else { + $form_state['values']['project_issue_notification']['projects']['new']['nid'] = $nid; + } + } +} + +/** * Form submission handler for project_issue_notification_user_form(). */ function project_issue_notification_user_form_submit($form, &$form_state) { // Update the global issue notification settings. $account = $form_state['values']['account']; - $account->project_issue_notification = $form_state['values']['project_issue_notification']; + + // First, save the default setting for this user. + $account->project_issue_notification = $form_state['values']['project_issue_notification']['projects']['default']; project_issue_notification_user_settings_save($account); - // Insert the new per-project settings. + unset($form_state['values']['project_issue_notification']['projects']['default']); + + // Now, see if they're trying to add notifications for a new project. + $new_project = $form_state['values']['project_issue_notification']['projects']['new']; + if (!empty($new_project['nid'])) { + project_issue_notification_project_setting_save($account->uid, $new_project['nid'], $new_project['level']); + } + // Either way, we're now done with this row. + unset($form_state['values']['project_issue_notification']['projects']['new']); + + // Finally, save any changes to the per-project settings. if (!empty($form_state['values']['project_issue_notification']['projects'])) { foreach ($form_state['values']['project_issue_notification']['projects'] as $nid => $level) { project_issue_notification_project_setting_save($account->uid, $nid, $level); diff --git a/project_issue.install b/project_issue.install index f5eed67..36e9e6b 100644 --- a/project_issue.install +++ b/project_issue.install @@ -293,7 +293,7 @@ function project_issue_schema() { 'default' => 0, ), 'level' => array( - 'description' => 'The global notification setting level. 0 = None, 1 = Flagged/Own, 2 = All.', + 'description' => 'The global default notification setting level. 0 = None, 1 = Flagged/Own, 2 = All.', 'type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, @@ -729,7 +729,7 @@ function project_issue_update_6009() { 'default' => 0, ), 'level' => array( - 'description' => 'The global notification setting level. 0 = None, 1 = Flagged/Own, 2 = All.', + 'description' => 'The global default notification setting level. 0 = None, 1 = Flagged/Own, 2 = All.', 'type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, diff --git a/project_issue.module b/project_issue.module index 8120b2d..6b6238e 100644 --- a/project_issue.module +++ b/project_issue.module @@ -1002,35 +1002,29 @@ function project_issue_notification_project_setting_load($uid, $nid) { * - PROJECT_ISSUE_NOTIFICATION_NONE * - PROJECT_ISSUE_NOTIFICATION_OWN * - PROJECT_ISSUE_NOTIFICATION_ALL - * When passing PROJECT_ISSUE_NOTIFICATION_NONE the user's project - * notification settings are deleted. * * @see project_issue_notification_project_setting_load() */ function project_issue_notification_project_setting_save($uid, $nid, $level) { - if ($level > PROJECT_ISSUE_NOTIFICATION_NONE) { - db_query("UPDATE {project_issue_notification_project} SET level = %d WHERE uid = %d AND nid = %d", array( - $level, - $uid, - $nid, - )); - if (!db_affected_rows()) { - db_query("INSERT INTO {project_issue_notification_project} (uid, nid, level) VALUES (%d, %d, %d)", array( - $uid, - $nid, - $level, - )); - } - } - else { - db_query("DELETE FROM {project_issue_notification_project} WHERE uid = %d AND nid = %d", array( - $uid, - $nid, - )); + db_query("UPDATE {project_issue_notification_project} SET level = %d WHERE uid = %d AND nid = %d", array($level, $uid, $nid)); + if (!db_affected_rows()) { + db_query("INSERT INTO {project_issue_notification_project} (uid, nid, level) VALUES (%d, %d, %d)", array($uid, $nid, $level)); } } /** + * Removes the project notification settings for a given user and project. + * + * @param $uid + * The ID of a user account. + * @param $nid + * The node ID of a project node. + */ +function project_issue_notification_project_setting_delete($uid, $nid) { + db_query("DELETE FROM {project_issue_notification_project} WHERE uid = %d AND nid = %d", array($uid, $nid)); +} + +/** * Implements hook_user(). */ function project_issue_user($op, $edit, $account) {