/** * Handles fetching the information for the helpdesk display within the unread and unread replies pages. * * The content is 'appended' below the unread posts information by way of a template layer. * * @since 2.0 */ function shd_unread_posts() { global $smcFunc, $context, $user_info, $sourcedir, $txt, $scripturl, $user_profile, $modSettings; // Are we using Dragooon's very swish mobile theme, or other wireless? If so, disable this. if (WIRELESS || isset($_REQUEST['thememode']) && $_REQUEST['thememode'] == 'mobile' || isset($_COOKIE['smf4m_cookie']) && $_COOKIE['smf4m_cookie'] == 'mobile') { $modSettings['shd_disable_unread'] = true; } // We're only displaying this to staff. We didn't do this check on bootstrapping, no sense doing it every page load. if (shd_allowed_to('shd_staff', 0) && empty($modSettings['shd_disable_unread'])) { // Get the data $context['shd_preferences'] = shd_load_user_prefs(); $context['shd_unread_info'] = array(); if (empty($context['shd_preferences']['display_unread_type']) || $context['shd_preferences']['display_unread_type'] == 'outstanding') { // Get all the outstanding tickets $context['block_title'] = $txt['shd_tickets_open']; $request = shd_db_query('', ' SELECT hdt.id_ticket, hdt.subject, hdt.id_ticket, hdt.num_replies, hdt.last_updated, hdtr_first.poster_name, hdt.urgency, hdt.status, hdt.id_member_started, hdt.id_member_assigned, hdt.id_last_msg AS log_read FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) WHERE {query_see_ticket} AND hdt.status IN ({array_int:status}) ORDER BY hdt.urgency DESC, hdt.last_updated', array('status' => array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF))); } elseif ($context['shd_preferences']['display_unread_type'] == 'unread') { // Only unread ones $context['block_title'] = $txt['shd_unread_tickets']; $request = shd_db_query('', ' SELECT hdt.id_ticket, hdt.subject, hdt.id_ticket, hdt.num_replies, hdt.last_updated, hdtr_first.poster_name, hdt.urgency, hdt.status, hdt.id_member_started, hdt.id_member_assigned, IFNULL(hdlr.id_msg, 0) AS log_read FROM {db_prefix}helpdesk_tickets AS hdt INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_first ON (hdt.id_first_msg = hdtr_first.id_msg) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr_last ON (hdt.id_last_msg = hdtr_last.id_msg) LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdt.id_ticket = hdlr.id_ticket AND hdlr.id_member = {int:user}) WHERE {query_see_ticket} AND hdt.status IN ({array_int:status}) AND (hdlr.id_msg IS NULL OR hdlr.id_msg < hdt.id_last_msg) ORDER BY hdt.urgency DESC, hdt.last_updated', array('user' => $context['user']['id'], 'status' => array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF))); } if (!empty($request)) { $members = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { $row['id_ticket_display'] = str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT); $row['updated'] = timeformat($row['last_updated']); $context['shd_unread_info'][] = $row; if ($row['id_member_started'] != 0) { $members[] = $row['id_member_started']; } if ($row['id_member_assigned'] != 0) { $members[] = $row['id_member_assigned']; } } loadMemberData(array_unique($members)); foreach ($context['shd_unread_info'] as $key => $ticket) { if (!empty($user_profile[$ticket['id_member_started']])) { $context['shd_unread_info'][$key]['ticket_starter'] = shd_profile_link($user_profile[$ticket['id_member_started']]['member_name'], $ticket['id_member_started']); } else { $context['shd_unread_info'][$key]['ticket_starter'] = $ticket['poster_name']; } if (!empty($user_profile[$ticket['id_member_assigned']])) { $context['shd_unread_info'][$key]['ticket_assigned'] = shd_profile_link($user_profile[$ticket['id_member_assigned']]['member_name'], $ticket['id_member_assigned']); } else { $context['shd_unread_info'][$key]['ticket_assigned'] = '<span class="error">' . $txt['shd_unassigned'] . '</span>'; } } // And set up the template too. loadTemplate('sd_template/SimpleDesk-Unread', 'helpdesk'); $context['template_layers'][] = 'shd_unread'; } } // OK, time to get out of here. If we're here, it's because we have a $_REQUEST['action'] of 'unread' or 'unreadreplies', both of which // are defined in $context['shd_unread_actions'] thanks to shd_init_actions back in Subs-SimpleDesk.php. require_once $sourcedir . '/' . $context['shd_unread_actions'][$_REQUEST['action']][0]; $context['shd_unread_actions'][$_REQUEST['action']][1](); }
function shd_profile_preferences($memID) { global $context, $txt, $scripturl, $sourcedir, $user_info, $smcFunc; $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_preferences']; $context['sub_template'] = 'shd_profile_preferences'; // Load the list of options and the user's individual opts $context['shd_preferences_options'] = shd_load_user_prefs(false); $context['member']['shd_preferences'] = shd_load_user_prefs($memID); foreach ($context['member']['shd_preferences'] as $pref => $value) { if (isset($context['shd_preferences_options']['prefs'][$pref])) { $thisgroup = $context['shd_preferences_options']['prefs'][$pref]['group']; if (!isset($context['shd_preferences_options']['groups'][$thisgroup])) { $context['shd_preferences_options']['groups'][$thisgroup] = array(); } $context['shd_preferences_options']['groups'][$thisgroup]['groups'][] = $pref; } } foreach ($context['shd_preferences_options']['groups'] as $group => $groupinfo) { if (empty($groupinfo)) { unset($context['shd_preferences_options']['groups'][$group]); } } // Are we saving any options? if (isset($_GET['save'])) { $changes = array('add' => array(), 'remove' => array()); // Step through each of the options we know are ours and check if they're defined here foreach ($context['member']['shd_preferences'] as $pref => $current_value) { $master_opt = $context['shd_preferences_options']['prefs'][$pref]; $new_value = $master_opt['default']; switch ($master_opt['type']) { case 'check': $new_value = !empty($_POST[$pref]) ? 1 : 0; break; case 'int': $new_value = isset($_POST[$pref]) ? (int) $_POST[$pref] : 0; break; case 'select': if (isset($_POST[$pref]) && isset($master_opt['options'][$_POST[$pref]])) { $new_value = $_POST[$pref]; } break; } if ($master_opt['default'] == $new_value) { // The new value is the same as default. If we already had non-default, remove the non-default value. if ($new_value != $current_value) { $changes['remove'][] = $pref; } } else { if ($new_value != $current_value) { $changes['add'][] = array($memID, $pref, (string) $new_value); } } // Finally, make sure whatever's in the array is actually what we've asked for $context['member']['shd_preferences'][$pref] = $new_value; } // Clean up the database and apply all the changes if (!empty($changes['add'])) { $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_preferences', array('id_member' => 'int', 'variable' => 'string', 'value' => 'string'), $changes['add'], array('id_member', 'variable')); } if (!empty($changes['remove'])) { $smcFunc['db_query']('', ' DELETE FROM {db_prefix}helpdesk_preferences WHERE id_member = {int:member} AND variable IN ({array_string:prefs})', array('member' => $memID, 'prefs' => $changes['remove'])); } } }
/** * Begins SimpleDesk general processing. * * Several things are done here, the results of which are unilaterally assumed by all other SimpleDesk functions. * - work out which departments are applicable, and which department we are currently in (as far as possible) * - set up general navigation * - see if the URL or POST data contains a ticket, if so sanitise and store that value * - see if a msg was specified in the URL, if so identify the relevant ticket * - add in the helpdesk CSS file * - identify the sub action to direct them to, then send them on their way. * * @since 1.0 */ function shd_main() { global $context, $txt, $settings, $sourcedir, $modSettings, $scripturl, $user_profile, $user_info, $smcFunc; // Basic sanity stuff if (!$modSettings['helpdesk_active']) { fatal_lang_error('shd_inactive', false); } // Let's be sneaky. Can they only access one department? If they can only access one department, put them there and make a note of it for later. $depts = shd_allowed_to('access_helpdesk', false); $context['shd_multi_dept'] = true; if (count($depts) == 1) { $_REQUEST['dept'] = $depts[0]; $context['shd_multi_dept'] = false; } elseif (empty($_REQUEST['dept']) && !empty($context['queried_dept']) && in_array($context['queried_dept'], $depts)) { $_REQUEST['dept'] = $context['queried_dept']; } $context['shd_department'] = isset($_REQUEST['dept']) && in_array($_REQUEST['dept'], $depts) ? (int) $_REQUEST['dept'] : 0; $context['shd_dept_link'] = !empty($context['shd_department']) && $context['shd_multi_dept'] ? ';dept=' . $context['shd_department'] : ''; shd_is_allowed_to('access_helpdesk', $context['shd_department']); // If we know the department up front, we probably should get it now. Tickets themselves will deal with this but most other places won't. // Note that we may already have loaded this if we went and got the department id earlier, but not always. if (!empty($context['shd_department']) && $context['shd_multi_dept'] && empty($context['shd_dept_name'])) { $query = $smcFunc['db_query']('', ' SELECT dept_name FROM {db_prefix}helpdesk_depts WHERE id_dept = {int:dept}', array('dept' => $context['shd_department'])); list($context['shd_dept_name']) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); } // Load stuff: preferences the core template - and any hook-required files $context['shd_preferences'] = shd_load_user_prefs(); $context['shd_home'] = 'action=helpdesk;sa=main'; loadTemplate('sd_template/SimpleDesk'); shd_load_plugin_files('helpdesk'); shd_load_plugin_langfiles('helpdesk'); // List of sub actions. $subactions = array('main' => array(null, 'shd_main_helpdesk'), 'dept' => array(null, 'shd_main_dept'), 'viewblock' => array(null, 'shd_view_block'), 'ticket' => array('SimpleDesk-Display.php', 'shd_view_ticket'), 'newticket' => array('SimpleDesk-Post.php', 'shd_post_ticket'), 'editticket' => array('SimpleDesk-Post.php', 'shd_post_ticket'), 'saveticket' => array('SimpleDesk-Post.php', 'shd_save_post'), 'reply' => array('SimpleDesk-Post.php', 'shd_post_reply'), 'savereply' => array('SimpleDesk-Post.php', 'shd_save_post'), 'editreply' => array('SimpleDesk-Post.php', 'shd_post_reply'), 'markunread' => array('SimpleDesk-MiscActions.php', 'shd_ticket_unread'), 'assign' => array('SimpleDesk-Assign.php', 'shd_assign'), 'assign2' => array('SimpleDesk-Assign.php', 'shd_assign2'), 'movedept' => array('SimpleDesk-MoveDept.php', 'shd_movedept'), 'movedept2' => array('SimpleDesk-MoveDept.php', 'shd_movedept2'), 'resolveticket' => array('SimpleDesk-MiscActions.php', 'shd_ticket_resolve'), 'relation' => array('SimpleDesk-MiscActions.php', 'shd_ticket_relation'), 'ajax' => array('SimpleDesk-AjaxHandler.php', 'shd_ajax'), 'privacychange' => array('SimpleDesk-MiscActions.php', 'shd_privacy_change_noajax'), 'urgencychange' => array('SimpleDesk-MiscActions.php', 'shd_urgency_change_noajax'), 'closedtickets' => array(null, 'shd_closed_tickets'), 'recyclebin' => array(null, 'shd_recycle_bin'), 'tickettotopic' => array('SimpleDesk-TicketTopicMove.php', 'shd_tickettotopic'), 'tickettotopic2' => array('SimpleDesk-TicketTopicMove.php', 'shd_tickettotopic2'), 'topictoticket' => array('SimpleDesk-TicketTopicMove.php', 'shd_topictoticket'), 'topictoticket2' => array('SimpleDesk-TicketTopicMove.php', 'shd_topictoticket2'), 'permadelete' => array('SimpleDesk-Delete.php', 'shd_perma_delete'), 'deleteticket' => array('SimpleDesk-Delete.php', 'shd_ticket_delete'), 'deletereply' => array('SimpleDesk-Delete.php', 'shd_reply_delete'), 'deleteattach' => array('SimpleDesk-Delete.php', 'shd_attach_delete'), 'restoreticket' => array('SimpleDesk-Delete.php', 'shd_ticket_restore'), 'restorereply' => array('SimpleDesk-Delete.php', 'shd_reply_restore'), 'emaillog' => array('SimpleDesk-Notifications.php', 'shd_notify_popup'), 'notify' => array('SimpleDesk-Notifications.php', 'shd_notify_ticket_options'), 'search' => array('SimpleDesk-Search.php', 'shd_search'), 'search2' => array('SimpleDesk-Search.php', 'shd_search2')); // Navigation menu $context['navigation'] = array('main' => array('text' => 'shd_home', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=main'), 'dept' => array('text' => 'shd_departments', 'test' => 'shd_multi_dept', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=dept'), 'newticket' => array('text' => 'shd_new_ticket', 'test' => 'can_new_ticket', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=newticket' . $context['shd_dept_link']), 'newticketproxy' => array('text' => 'shd_new_ticket_proxy', 'test' => 'can_proxy_ticket', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=newticket;proxy' . $context['shd_dept_link']), 'closedtickets' => array('text' => 'shd_tickets_closed', 'test' => 'can_view_closed', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=closedtickets' . $context['shd_dept_link']), 'recyclebin' => array('text' => 'shd_recycle_bin', 'test' => 'can_view_recycle', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=recyclebin' . $context['shd_dept_link']), 'search' => array('text' => 'shd_search_menu', 'test' => 'can_shd_search', 'lang' => true, 'url' => $scripturl . '?action=helpdesk;sa=search'), 'back' => array('text' => 'shd_back_to_hd', 'test' => 'display_back_to_hd', 'lang' => true, 'url' => $scripturl . '?' . $context['shd_home'] . $context['shd_dept_link']), 'options' => array('text' => 'shd_options', 'test' => 'can_view_options', 'lang' => true, 'url' => $scripturl . '?action=profile;area=hd_prefs')); // Build the link tree. $context['linktree'][] = array('url' => $scripturl . '?action=helpdesk;sa=main', 'name' => $txt['shd_helpdesk']); if (!$context['shd_multi_dept']) { $context['linktree'][] = array('url' => $scripturl . '?' . $context['shd_home'], 'name' => $txt['shd_linktree_tickets']); } // See if a ticket has been specified, like $topic can be. if (!empty($_REQUEST['ticket'])) { if (strpos($_REQUEST['ticket'], '.') === false) { $context['ticket_id'] = (int) $_REQUEST['ticket']; $context['ticket_start'] = 0; } else { list($context['ticket_id'], $context['ticket_start']) = explode('.', $_REQUEST['ticket']); $context['ticket_id'] = (int) $context['ticket_id']; if (!is_numeric($context['ticket_start'])) { // Let's see if it's 'new' first. If it is, great, we'll figure out the new point then throw it at the next one. if (substr($context['ticket_start'], 0, 3) == 'new') { $query = shd_db_query('', ' SELECT IFNULL(hdlr.id_msg, -1) + 1 AS new_from FROM {db_prefix}helpdesk_tickets AS hdt LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdlr.id_ticket = {int:ticket} AND hdlr.id_member = {int:member}) WHERE {query_see_ticket} AND hdt.id_ticket = {int:ticket} LIMIT 1', array('member' => $user_info['id'], 'ticket' => $context['ticket_id'])); list($new_from) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); $context['ticket_start'] = 'msg' . $new_from; $context['ticket_start_newfrom'] = $new_from; } if (substr($context['ticket_start'], 0, 3) == 'msg') { $virtual_msg = (int) substr($context['ticket_start'], 3); $query = shd_db_query('', ' SELECT COUNT(hdtr.id_msg) FROM {db_prefix}helpdesk_ticket_replies AS hdtr INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) WHERE {query_see_ticket} AND hdtr.id_ticket = {int:ticket} AND hdtr.id_msg > hdt.id_first_msg AND hdtr.id_msg < {int:virtual_msg}' . (!isset($_GET['recycle']) ? ' AND hdtr.message_status = {int:message_notdel}' : ''), array('ticket' => $context['ticket_id'], 'virtual_msg' => $virtual_msg, 'message_notdel' => MSG_STATUS_NORMAL)); list($context['ticket_start']) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); } } else { $context['ticket_start'] = (int) $context['ticket_start']; // it IS numeric but let's make sure it's the right kind of number $context['ticket_start_natural'] = true; } } } if (empty($context['ticket_start_newfrom'])) { $context['ticket_start_newfrom'] = empty($context['ticket_start']) ? 0 : $context['ticket_start']; } // Do we have just a message id? We can get the ticket from that - but only if we don't already have a ticket id! $_REQUEST['msg'] = !empty($_REQUEST['msg']) ? (int) $_REQUEST['msg'] : 0; if (!empty($_REQUEST['msg']) && empty($context['ticket_id'])) { $query = shd_db_query('', ' SELECT hdt.id_ticket, hdtr.id_msg FROM {db_prefix}helpdesk_ticket_replies AS hdtr INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket) WHERE {query_see_ticket} AND hdtr.id_msg = {int:msg}', array('msg' => $_REQUEST['msg'])); if ($row = $smcFunc['db_fetch_row']($query)) { $context['ticket_id'] = (int) $row[0]; } $smcFunc['db_free_result']($query); } $context['items_per_page'] = 10; $context['start'] = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0; // Load the custom CSS. if (empty($context['html_headers'])) { $context['html_headers'] = ''; } $context['html_headers'] .= ' <link rel="stylesheet" type="text/css" href="' . (file_exists($settings['theme_dir'] . '/css/helpdesk.css') ? $settings['theme_url'] . '/css/helpdesk.css' : $settings['default_theme_url'] . '/css/helpdesk.css') . '?' . $context['shd_css_version'] . '" /> <script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/helpdesk.js?' . $context['shd_scripts_version'] . '"></script>'; // A custom css? if (file_exists($settings['default_theme_url'] . '/css/helpdesk_custom.css')) { $context['html_headers'] .= ' <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk_custom.css?' . $context['shd_css_version'] . '" />'; } if (file_exists($settings['theme_dir'] . '/css/helpdesk_custom.css')) { $context['html_headers'] .= ' <link rel="stylesheet" type="text/css" href="' . $settings['theme_url'] . '/css/helpdesk_custom.css?' . $context['shd_css_version'] . '" />'; } // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) call_integration_hook('shd_hook_helpdesk', array(&$subactions)); // What are we doing? $_REQUEST['sa'] = !empty($_REQUEST['sa']) && isset($subactions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'main'; $context['sub_action'] = $subactions[$_REQUEST['sa']]; $context['can_new_ticket'] = shd_allowed_to('shd_new_ticket', $context['shd_department']); $context['can_proxy_ticket'] = $context['can_new_ticket'] && shd_allowed_to('shd_post_proxy', $context['shd_department']); $context['can_view_closed'] = shd_allowed_to(array('shd_view_closed_own', 'shd_view_closed_any'), $context['shd_department']); $context['can_view_recycle'] = shd_allowed_to('shd_access_recyclebin', $context['shd_department']); $context['display_back_to_hd'] = !in_array($_REQUEST['sa'], array('main', 'viewblock', 'recyclebin', 'closedtickets', 'dept')); $context['can_shd_search'] = shd_allowed_to('shd_search', 0); $context['can_view_options'] = shd_allowed_to(array('shd_view_preferences_own', 'shd_view_preferences_any'), 0); // Highlight the correct button. if (isset($context['navigation'][$_REQUEST['sa']])) { $context['navigation'][$_REQUEST['sa']]['active'] = true; } // Send them away. if ($context['sub_action'][0] !== null) { require $sourcedir . '/sd_source/' . $context['sub_action'][0]; } $context['sub_action'][1](); // Maintenance mode? If it were, the helpdesk is considered inactive for the purposes of everything to all but those without admin-helpdesk rights - but we must have them if we're here! if (!empty($modSettings['shd_maintenance_mode']) && $_REQUEST['sa'] != 'ajax') { $context['template_layers'][] = 'shd_maintenance'; } call_integration_hook('shd_hook_after_main'); }
/** * 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_assign(&$ticket, &$assignment) { global $smcFunc, $context, $modSettings, $scripturl; if (empty($modSettings['shd_notify_assign_me']) && empty($modSettings['shd_notify_assign_own'])) { return; } $ticketinfo = shd_load_ticket($ticket); // ticket starter = $ticketinfo['starter_id'] // $assignment = user id of assignee (0 for no longer being assigned) $notify_data = array('members' => array(), 'ticketlink' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket . '.0', 'subject' => $ticketinfo['subject'], 'ticket' => $ticket); // Get the default preferences $prefs = shd_load_user_prefs(false); $pref_groups = $prefs['groups']; $base_prefs = $prefs['prefs']; $members = array(); $member_prefs = array(); // So, does the starter want to be notified if the ticket is assigned? if (!empty($ticketinfo['starter_id']) && !empty($modSettings['shd_notify_assign_own'])) { $members[$ticketinfo['starter_id']] = 'assign_own'; $member_prefs[$ticketinfo['starter_id']] = $base_prefs['notify_assign_own']['default']; } // Does the assignee want to be notified? This assumes it is actually a person... if (!empty($assignment) && !empty($modSettings['shd_notify_assign_me'])) { $members[$assignment] = 'assign_me'; $member_prefs[$assignment] = $base_prefs['notify_assign_me']['default']; } if (isset($members[$context['user']['id']])) { unset($members[$context['user']['id']]); } if (empty($members)) { return; } // whoops // OK, so we've figured out what we'd send to folks. Now let's see what the users want $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('notify_assign_me', 'notify_assign_own'))); while ($row = $smcFunc['db_fetch_assoc']($query)) { $row['id_member'] = (int) $row['id_member']; if ($row['variable'] == 'notify_' . $members[$row['id_member']]) { $member_prefs[$row['id_member']] = $row['value']; } } $smcFunc['db_free_result']($query); // unset $members where member pref doesn't fit foreach ($member_prefs as $id => $value) { if (empty($value)) { unset($members[$id]); } } // move $members to $notify_data['members'] $notify_data['members'] = $members; // AAAAAAAAAAAAND WE'RE OFF! if (!empty($notify_data['members'])) { shd_notify_users($notify_data); } }
/** * The start point for all interaction with the SimpleDesk administration area. * * Enforces that users attempting to access the area have either forum or helpdesk administrative privileges, loads the SimpleDesk * administrative CSS and Javascript and promptly directs users to the specific function for the task they are performing. * * @since 1.0 */ function shd_admin_main() { global $context, $scripturl, $sourcedir, $settings, $txt, $modSettings, $scripturl; shd_init(); shd_load_language('sd_language/SimpleDeskAdmin'); // Kick them in the kneecaps! if (!shd_allowed_to('admin_helpdesk', 0)) { isAllowedTo('admin_forum'); } // Templates and stuff (like hook files) loadTemplate('sd_template/SimpleDesk-Admin'); $context['template_layers'][] = 'shd_nojs'; $context['shd_preferences'] = shd_load_user_prefs(); shd_load_plugin_files('hdadmin'); shd_load_plugin_langfiles('hdadmin'); // Load some extra CSS $context['html_headers'] .= ' <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk_admin.css?' . $context['shd_css_version'] . '" /> <link rel="stylesheet" type="text/css" href="' . $settings['default_theme_url'] . '/css/helpdesk.css?' . $context['shd_css_version'] . '" /> <script type="text/javascript" src="' . $settings['default_theme_url'] . '/scripts/helpdesk_admin.js?' . $context['shd_scripts_version'] . '"></script>'; $context['page_title'] = $txt['shd_admin_title']; // We need this for later require_once $sourcedir . '/ManageServer.php'; // Create some subactions $subActions = array('helpdesk_info' => array(null, 'shd_admin_info'), 'helpdesk_options' => array(null, 'shd_admin_options'), 'helpdesk_cannedreplies' => array('SimpleDesk-AdminCannedReplies.php', 'shd_admin_canned'), 'helpdesk_customfield' => array('SimpleDesk-AdminCustomField.php', 'shd_admin_custom'), 'helpdesk_depts' => array('SimpleDesk-AdminDepartments.php', 'shd_admin_departments'), 'helpdesk_permissions' => array('SimpleDesk-AdminPermissions.php', 'shd_admin_permissions'), 'helpdesk_plugins' => array('SimpleDesk-AdminPlugins.php', 'shd_admin_plugins'), 'helpdesk_maint' => array('SimpleDesk-AdminMaint.php', 'shd_admin_maint')); // Int hooks - after we basically set everything up (so it's manipulatable by the hook, but before we do the last bits of finalisation) call_integration_hook('shd_hook_hdadmin', array(&$subActions)); // Make sure we can find a subaction. If not set, default to info $_REQUEST['area'] = isset($_REQUEST['area']) && isset($subActions[$_REQUEST['area']]) ? $_REQUEST['area'] : 'helpdesk_info'; $context['sub_action'] = $_REQUEST['area']; if (!empty($subActions[$_REQUEST['area']][0])) { require_once $sourcedir . '/sd_source/' . $subActions[$_REQUEST['area']][0]; } // Call our subaction if ($_REQUEST['area'] == 'helpdesk_options') { $subActions[$_REQUEST['area']][1](false); } else { $subActions[$_REQUEST['area']][1](); } // Important ACS666 check up. if (isset($_REQUEST['cookies'])) { shd_do_important(); } // Maintenance mode? If it were, the helpdesk is considered inactive for the purposes of everything to all but those without admin-helpdesk rights - but we must have them if we're here! if (!empty($modSettings['shd_maintenance_mode'])) { loadTemplate('sd_template/SimpleDesk'); $temp_layers = $context['template_layers']; $context['template_layers'] = array(); $added = false; foreach ($temp_layers as $layer) { $context['template_layers'][] = $layer; if ($layer == 'body') { $context['template_layers'][] = 'shd_maintenance'; $added = true; } } // Well, we tried to add it as near the top as possible, but not all themes use the standard body layer. if (!$added) { $context['template_layers'][] = 'shd_maintenance'; } } // Also, fix up the link tree while we're here. $linktree = $context['linktree']; $context['linktree'] = array(); foreach ($linktree as $linktreeitem) { $context['linktree'][] = $linktreeitem; if ($linktreeitem['url'] == $scripturl . '?action=admin') { $context['linktree'][] = array('url' => $scripturl . '?action=admin;area=helpdesk_info', 'name' => $txt['shd_helpdesk']); } } }