/** * Provide the list of possible notification recipients. * * @since 2.0 */ function shd_ajax_notify() { global $txt, $context, $smcFunc, $user_profile, $modSettings, $sourcedir; $session_check = checkSession('get', '', false); // check the session but don't die fatally. if (!empty($session_check)) { return $context['ajax_return'] = array('error' => $txt[$session_check]); } shd_load_language('sd_language/SimpleDeskNotifications'); require_once $sourcedir . '/sd_source/SimpleDesk-Notifications.php'; if (!empty($context['ticket_id'])) { $query = shd_db_query('', ' SELECT hdt.private, hdt.id_member_started, id_member_assigned, id_dept, status FROM {db_prefix}helpdesk_tickets AS hdt WHERE {query_see_ticket} AND hdt.id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); if ($smcFunc['db_num_rows']($query) != 0) { $ticket = $smcFunc['db_fetch_assoc']($query); } $smcFunc['db_free_result']($query); } if (empty($ticket) || !shd_allowed_to('shd_singleton_email', $ticket['id_dept']) || $ticket['status'] == TICKET_STATUS_CLOSED || $ticket['status'] == TICKET_STATUS_DELETED) { return $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); } // So, we need to start figuring out who's going to be notified, who won't be and who we might be interested in notifying. $notify_list = array('being_notified' => array(), 'optional' => array(), 'optional_butoff' => array()); // Let's get all the possible actual people. The possible people who can be notified... well, they're staff. $staff = shd_get_visible_list($ticket['id_dept'], $ticket['private'], $ticket['id_member_started'], empty($modSettings['shd_admins_not_assignable']), false); // Let's start figuring it out then! First, get the big ol' lists. $query = $smcFunc['db_query']('', ' SELECT id_member, notify_state FROM {db_prefix}helpdesk_notify_override WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); while ($row = $smcFunc['db_fetch_assoc']($query)) { $notify_list[$row['notify_state'] == NOTIFY_NEVER ? 'optional_butoff' : 'being_notified'][$row['id_member']] = true; } // Did we exclude admins? If we did, we would have scooped the list of admins. If they're in the 'not being notified but you can...' list, remove them. if (!empty($context['list_admin_exclude'])) { foreach ($context['list_admin_exclude'] as $user_id) { if (isset($notify_list['optional_butoff'][$user_id])) { unset($notify_list['optional_butoff'][$user_id]); } } } // Now we get the list by preferences. This is where it starts to get complicated. $possible_members = array(); // People who want replies to their own ticket, without including the ticket starter because they'd know about it... if (!empty($modSettings['shd_notify_new_reply_own']) && $context['user']['id'] != $ticket['id_member_started']) { $possible_members[$ticket['id_member_started']]['new_reply_own'] = true; } // The ticket is assigned to someone and they want to be notified if it changes. if (!empty($modSettings['shd_notify_new_reply_assigned']) && !empty($ticket['id_member_assigned']) && $context['user']['id'] != $ticket['id_member_assigned']) { $possible_members[$ticket['id_member_assigned']]['new_reply_assigned'] = true; } // So, if you're staff, and you've replied to this ticket before, do you want to be notified this time? if (!empty($modSettings['shd_notify_new_reply_previous'])) { $query = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}helpdesk_ticket_replies WHERE id_ticket = {int:ticket} GROUP BY id_member', array('ticket' => $context['ticket_id'])); $responders = array(); while ($row = $smcFunc['db_fetch_row']($query)) { $responders[] = $row[0]; } // this shouldn't be nil, ever, because we're replying, so the topic already exists so there's at least one name in there... $smcFunc['db_free_result']($query); $responders = array_intersect($responders, $staff); foreach ($responders as $id) { $possible_members[$id]['new_reply_previous'] = true; } } // If you're staff, did you have 'spam my inbox every single time' selected? if (!empty($modSettings['shd_notify_new_reply_any'])) { foreach ($staff as $id) { $possible_members[$id]['new_reply_any'] = true; } } // Now we have the list of possibles, exclude everyone who is either set to on, or off, since we don't need to query those for preferences. foreach ($possible_members as $id => $type_list) { if (isset($notify_list['being_notified'][$id]) || isset($notify_list['optional_butoff'][$id])) { unset($possible_members[$id]); } } if (!empty($possible_members)) { // Get the default preferences $prefs = shd_load_user_prefs(false); $pref_groups = $prefs['groups']; $base_prefs = $prefs['prefs']; // Build a list of users -> default prefs. We know this is for the list of possible contenders only. $member_prefs = array(); $pref_list = array(); foreach ($possible_members as $id => $type_list) { foreach ($type_list as $type => $value) { $member_prefs[$id][$type] = $base_prefs['notify_' . $type]['default']; $pref_list['notify_' . $type] = true; } } // Grab pref list from DB for these users and update $query = $smcFunc['db_query']('', ' SELECT id_member, variable, value FROM {db_prefix}helpdesk_preferences WHERE id_member IN ({array_int:members}) AND variable IN ({array_string:variables})', array('members' => array_keys($possible_members), 'variables' => array_keys($pref_list))); while ($row = $smcFunc['db_fetch_assoc']($query)) { $row['id_member'] = (int) $row['id_member']; $variable = substr($row['variable'], 7); if (isset($member_prefs[$row['id_member']][$variable])) { $member_prefs[$row['id_member']][$variable] = $row['value']; } } $smcFunc['db_free_result']($query); // unset $members where member pref doesn't indicate they want it on. foreach ($member_prefs as $id => $value) { foreach ($value as $pref_id => $pref_item) { if (empty($pref_item)) { unset($possible_members[$id][$pref_id]); } } } // Now, it's possible that we have a ticket that the starter can't see, but that their preferences would indicate they'd like a reply. // What should be done here is to remove them from the automatic list, and make them part of the ping list instead. if (!empty($ticket['id_member_started']) && !in_array($ticket['id_member_started'], $staff)) { $possible_members[$ticket['id_member_started']] = array(); } // Now the clever bit, we've taken everyone who wasn't on the normal notify list, and figured out what their preferences are. // We now traverse $possible_members by id, if the array is empty, we know none of their preferences accounted for emails - so they're possible. // Otherwise we add them to the list of being notified. foreach ($possible_members as $id => $list) { if (empty($list)) { $notify_list['optional'][$id] = true; } else { $notify_list['being_notified'][$id] = true; } } } // By now we have three lists that include people who will be notified, people who could be notified, and people who don't really want to be. // Let's translate that into a list of people that we can make use of. $members = array_merge(array_keys($notify_list['being_notified']), array_keys($notify_list['optional']), array_keys($notify_list['optional_butoff'])); if (!empty($members)) { // Get everyone's name. $loaded = loadMemberData($members); foreach ($loaded as $user) { if (!empty($user_profile[$user]) && $user_profile[$user]['is_activated'] > 0 && $user_profile[$user]['is_activated'] < 10) { // active & not banned $people[$user] = array('id' => $user, 'name' => $user_profile[$user]['real_name']); } } // Right, now let's step through and tidy up the three lists foreach ($notify_list as $list_type => $list_members) { foreach ($list_members as $id_member => $data) { if (isset($people[$id_member]) && $id_member != $context['user']['id']) { // We really shouldn't be in this list. $list_members[$id_member] = $people[$id_member]['name']; } else { unset($list_members[$id_member]); } } if (!empty($list_members)) { asort($list_members); array_walk($list_members, 'shd_format_notify_name', $ticket['id_member_started']); $notify_list[$list_type] = $list_members; } else { unset($notify_list[$list_type]); } } } if (empty($notify_list) || empty($members)) { return $context['ajax_raw'] = '<notify><![C' . 'DATA[' . cleanXml($txt['shd_ping_none']) . ']' . ']></notify>'; } else { ob_start(); echo '<notify><![C', 'DATA['; $selected = array(); if (!empty($_GET['list'])) { $_GET['list'] = explode(',', $_GET['list']); foreach ($_GET['list'] as $id) { if ((int) $id > 0) { $selected[] = (int) $id; } } } if (!empty($notify_list['being_notified'])) { echo '<span class="shd_ajax_head">', $txt['shd_ping_already_' . (count($notify_list['being_notified']) == 1 ? '1' : 'n')], '</span><br />', implode(', ', $notify_list['being_notified']); } if (!empty($notify_list['optional'])) { if (!empty($notify_list['being_notified'])) { echo '<br /><br />'; } echo '<span class="shd_ajax_head">', $txt['shd_ping_' . (count($notify_list['optional']) == 1 ? '1' : 'n')], '</span><br />'; foreach ($notify_list['optional'] as $id => $member) { echo '<div class="shd_ajaxnotify"><input type="checkbox" name="notify[', $id, ']" value="', $id, '"', in_array($id, $selected) ? ' checked="checked"' : '', ' class="input_check" /> ', $member, '</div>'; } } if (!empty($notify_list['optional_butoff'])) { if (!empty($notify_list['being_notified']) || !empty($notify_list['optional_butoff'])) { echo '<br /><br />'; } echo '<span class="shd_ajax_head">', $txt['shd_ping_none_' . (count($notify_list['optional_butoff']) == 1 ? '1' : 'n')], '</span><br />'; foreach ($notify_list['optional_butoff'] as $id => $member) { echo '<div class="shd_ajaxnotify"><input type="checkbox" name="notify[', $id, ']" value="', $id, '"', in_array($id, $selected) ? ' checked="checked"' : '', ' class="input_check" /> ', $member, '</div>'; } } echo ']', ']></notify>'; $content = ob_get_clean(); return $context['ajax_raw'] = cleanXml($content); } }
function shd_notifications_notify_newreply(&$msgOptions, &$ticketOptions, &$posterOptions) { global $smcFunc, $context, $modSettings, $scripturl; // We did actually get a reply? Sometimes shd_modify_ticket_post() is called for other things, not just on reply. if (empty($msgOptions['body'])) { return; } // Alternatively, they might be doing a silent update. if (!empty($_POST['silent_update']) && shd_allowed_to('shd_silent_update', $ticketOptions['dept'])) { return; } // We're doing various things here, so grab some general details, not just what we may have been passed before. $ticketinfo = shd_load_ticket($ticketOptions['id']); // $staff is the sum total of staff + ticket starter, subject to visibility of the ticket. $staff = shd_get_visible_list($ticketOptions['dept'], $ticketinfo['private'], $ticketinfo['starter_id'], empty($modSettings['shd_admins_not_assignable']), false); // Might as well kick this off here. $notify_data = array('members' => array(), 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticketOptions['id'] . '.msg' . $msgOptions['id'] . '#msg' . $msgOptions['id'], 'subject' => $ticketinfo['subject'], 'ticket' => $ticketOptions['id'], 'msg' => $msgOptions['id'], 'body' => $msgOptions['body'], 'poster_name' => $posterOptions['name']); $members = array(); // who should get what type of notification, preferences depending // Someone replied to MY ticket? And it isn't me? I might want you to tell me about it! if (!empty($ticketinfo['starter_id']) && !empty($modSettings['shd_notify_new_reply_own']) && $posterOptions['id'] != $ticketinfo['starter_id'] && in_array($ticketinfo['starter_id'], $staff)) { $members[$ticketinfo['starter_id']]['new_reply_own'] = true; } // So this is a ticket I'm supposed to deal with... has someone said something I missed? (And just in case it's our ticket, don't send another) if (!empty($modSettings['shd_notify_new_reply_assigned'])) { if (!empty($ticketinfo['assigned_id']) && $posterOptions['id'] != $ticketinfo['assigned_id'] && in_array($ticketinfo['assigned_id'], $staff)) { $members[$ticketinfo['assigned_id']]['new_reply_assigned'] = true; } } // So, if you're staff, and you've replied to a ticket before, do you want to be notified this time? if (!empty($modSettings['shd_notify_new_reply_previous'])) { $query = $smcFunc['db_query']('', ' SELECT id_member FROM {db_prefix}helpdesk_ticket_replies WHERE id_ticket = {int:ticket} GROUP BY id_member', array('ticket' => $ticketOptions['id'])); $responders = array(); while ($row = $smcFunc['db_fetch_row']($query)) { $responders[] = $row[0]; } // this shouldn't be nil, ever, because we're replying, so the topic already exists so there's at least one name in there... $smcFunc['db_free_result']($query); $responders = array_intersect($responders, $staff); foreach ($responders as $id) { $members[$id]['new_reply_previous'] = true; } } // Do staff just want general notifications about everything? Don't change things if they already had a notice though, this is just for the rabble at the back if (!empty($modSettings['shd_notify_new_reply_any'])) { foreach ($staff as $id) { $members[$id]['new_reply_any'] = true; } } if (empty($members)) { return; } // Get the default preferences $prefs = shd_load_user_prefs(false); $pref_groups = $prefs['groups']; $base_prefs = $prefs['prefs']; // Build a list of users -> default prefs $member_prefs = array(); $pref_list = array(); foreach ($members as $id => $type_list) { foreach ($type_list as $type => $value) { $member_prefs[$id][$type] = $base_prefs['notify_' . $type]['default']; $pref_list['notify_' . $type] = true; } } // Grab pref list from DB for these users and update $query = $smcFunc['db_query']('', ' SELECT id_member, variable, value FROM {db_prefix}helpdesk_preferences WHERE id_member IN ({array_int:members}) AND variable IN ({array_string:variables})', array('members' => array_keys($members), 'variables' => array_keys($pref_list))); while ($row = $smcFunc['db_fetch_assoc']($query)) { $row['id_member'] = (int) $row['id_member']; $variable = substr($row['variable'], 7); if (isset($member_prefs[$row['id_member']][$variable])) { $member_prefs[$row['id_member']][$variable] = $row['value']; } } $smcFunc['db_free_result']($query); // unset $members where member pref doesn't fit foreach ($member_prefs as $id => $value) { foreach ($value as $pref_id => $pref_item) { if (empty($pref_item)) { unset($members[$id][$pref_id]); } } } // Lastly, get the list of people who wanted to be notified through their preferences - and anyone who wanted to be excluded. $overrides = shd_query_monitor_list($ticketOptions['id']); foreach ($overrides['always_notify'] as $member_id) { $members[$member_id]['monitor'] = true; } // And apply exclusions foreach ($overrides['never_notify'] as $member_id) { unset($members[$member_id]); } // And now, finally, receive the list of possible cases from the notification doodad, and verify against a list of possible people. if ($context['can_ping']) { if (!empty($_POST['notify']) && is_array($_POST['notify'])) { $staff[] = $ticketinfo['starter_id']; // Add the ticket starter as a possible candidate. foreach ($_POST['notify'] as $id) { if (in_array((int) $id, $staff)) { $members[$id]['ping'] = true; } } } elseif (!empty($_REQUEST['list'])) { $list = explode(',', $_REQUEST['list']); foreach ($list as $id) { if (in_array((int) $id, $staff)) { $members[$id]['ping'] = true; } } } } // Lastly, prevent the reply author getting notified for any reason. if (!empty($members[$context['user']['id']])) { unset($members[$context['user']['id']]); } // So, at this point, $members contains a list of the members and a sequence of the possible messages they could get. We need to make some sense of it. $notify_data['members'] = array(); foreach ($members as $member_id => $notify_list) { if (empty($notify_list)) { continue; } // Preferences killed all their possible choices. // We want the first non empty value on the list, and that's all. $item = ''; foreach ($notify_list as $k => $v) { if (!empty($v)) { $item = $k; break; } } if (!empty($item)) { $notify_data['members'][$member_id] = $item; } // We want the first one only. } // AAAAAAAAAAAAND WE'RE OFF! if (!empty($notify_data['members'])) { shd_notify_users($notify_data); } }