Example #1
0
/**
 *	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']));
        }
    }
}
Example #3
0
/**
 *	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);
    }
}
Example #6
0
/**
 *	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']);
        }
    }
}