Ejemplo n.º 1
0
/**
 *	Sets up the profile menu additions.
 *
 *	@param array $profile_areas Current profile_areas.
 *
 *	@since 2.0
*/
function shd_profile_areas(&$profile_areas)
{
    global $sourcedir, $modSettings, $context, $txt;
    static $called = false;
    if ($called) {
        return;
    }
    if (empty($called)) {
        $called = true;
    }
    // SimpleDesk sections. Added here after the initial cleaning is done, so that we can do our own permission checks without arguing with SMF's system (so much)
    if (empty($modSettings['helpdesk_active'])) {
        return;
    }
    shd_load_language('sd_language/SimpleDeskProfile');
    // Put it here so we can reuse it for the left menu a bit
    $context['helpdesk_menu'] = array('title' => $txt['shd_profile_area'], 'areas' => array('hd_profile' => array('label' => $txt['shd_profile_main'], 'file' => 'sd_source/SimpleDesk-Profile.php', 'function' => 'shd_profile_main', 'enabled' => shd_allowed_to('shd_view_profile_any') || $context['user']['is_owner'] && shd_allowed_to('shd_view_profile_own'), 'permission' => array('own' => array('is_not_guest'), 'any' => array('is_not_guest'))), 'hd_prefs' => array('label' => $txt['shd_profile_preferences'], 'file' => 'sd_source/SimpleDesk-Profile.php', 'function' => 'shd_profile_main', 'enabled' => shd_allowed_to('shd_view_preferences_any') || $context['user']['is_owner'] && shd_allowed_to('shd_view_preferences_own'), 'permission' => array('own' => array('shd_view_preferences_own'), 'any' => array('shd_view_preferences_any'))), 'hd_showtickets' => array('label' => $txt['shd_profile_show_tickets'], 'file' => 'sd_source/SimpleDesk-Profile.php', 'function' => 'shd_profile_main', 'enabled' => $context['user']['is_owner'] && shd_allowed_to('shd_view_ticket_own') || shd_allowed_to('shd_view_ticket_any'), 'permission' => array('own' => array('shd_view_ticket_own'), 'any' => array('shd_view_ticket_any'))), 'hd_permissions' => array('label' => $txt['shd_profile_permissions'], 'file' => 'sd_source/SimpleDesk-Profile.php', 'function' => 'shd_profile_main', 'enabled' => shd_allowed_to('admin_helpdesk'), 'permission' => array('own' => array('admin_helpdesk'), 'any' => array('admin_helpdesk'))), 'hd_actionlog' => array('label' => $txt['shd_profile_actionlog'], 'file' => 'sd_source/SimpleDesk-Profile.php', 'function' => 'shd_profile_main', 'enabled' => empty($modSettings['shd_disable_action_log']) && (shd_allowed_to('shd_view_profile_log_any') || $context['user']['is_owner'] && shd_allowed_to('shd_view_profile_log_own')), 'permission' => array('own' => array('shd_view_profile_log_own'), 'any' => array('shd_view_profile_log_any')))));
    // Kill the existing profile menu but save it in a temporary place first.
    $old_profile_areas = $profile_areas;
    $profile_areas = array();
    // Now, where we add this depends very much on what mode we're in. In HD only mode, we want our menu first before anything else.
    if (!empty($modSettings['shd_helpdesk_only'])) {
        require_once $sourcedir . '/Profile-Modify.php';
        // Move some stuff around.
        $context['helpdesk_menu']['areas']['permissions'] = array('label' => $txt['shd_show_forum_permissions'], 'file' => 'Profile-View.php', 'function' => 'showPermissions', 'enabled' => allowedTo('manage_permissions'));
        $context['helpdesk_menu']['areas']['tracking'] = array('label' => $txt['trackUser'], 'file' => 'Profile-View.php', 'function' => 'tracking', 'subsections' => array('activity' => array($txt['trackActivity'], 'moderate_forum'), 'ip' => array($txt['trackIP'], 'moderate_forum'), 'edits' => array($txt['trackEdits'], 'moderate_forum')), 'enabled' => allowedTo('moderate_forum'));
        $profile_areas['helpdesk'] = $context['helpdesk_menu'];
        $profile_areas += $old_profile_areas;
        unset($profile_areas['info']['areas']['permissions'], $profile_areas['info']['areas']['tracking']);
        $remove = array('info' => array('summary', 'statistics', 'showposts', 'viewwarning'), 'edit_profile' => array('forumprofile', 'ignoreboards', 'lists', 'notification'), 'profile_action' => array('issuewarning'));
        if (!empty($modSettings['shd_disable_pm'])) {
            $remove['profile_action'][] = 'sendpm';
            $remove['edit_profile'][] = 'pmprefs';
        }
        foreach ($remove as $area => $items) {
            foreach ($items as $item) {
                if (!empty($profile_areas[$area]['areas'][$item])) {
                    $profile_areas[$area]['areas'][$item]['enabled'] = false;
                }
            }
        }
        $profile_areas['edit_profile']['areas']['theme']['file'] = 'sd_source/SimpleDesk-Profile.php';
        $profile_areas['edit_profile']['areas']['theme']['function'] = 'shd_profile_theme_wrapper';
    } else {
        foreach ($old_profile_areas as $area => $details) {
            if ($area == 'edit_profile') {
                $profile_areas['helpdesk'] = $context['helpdesk_menu'];
            }
            $profile_areas[$area] = $details;
        }
    }
    // Now engage any hooks.
    call_integration_hook('shd_hook_profilemenu', array(&$profile_areas));
}
Ejemplo n.º 2
0
function shd_profile_actionlog($memID)
{
    global $context, $txt, $scripturl, $sourcedir, $user_info, $settings;
    loadTemplate('sd_template/SimpleDesk-Profile');
    shd_load_language('sd_language/SimpleDeskProfile');
    require_once $sourcedir . '/sd_source/Subs-SimpleDeskAdmin.php';
    $context['action_log'] = shd_load_action_log_entries(-1, 10, '', '', 'la.id_member = ' . $memID);
    $context['action_log_count'] = shd_count_action_log_entries('la.id_member = ' . $memID);
    $context['action_full_log'] = allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk', 0);
    $context['page_title'] = $txt['shd_profile_area'] . ' - ' . $txt['shd_profile_actionlog'];
    $context['sub_template'] = 'shd_profile_actionlog';
}
Ejemplo n.º 3
0
/**
 *	Gather the data and prepare to display the ticket blocks.
 *
 *	Actually performs the queries to get data for each block, subject to the parameters specified by the calling functions.
 *
 *	It also sets up per-block pagination links, collects a variety of data (enough to populate all the columns as listed in shd_main_helpdesk,
 *	even if not entirely applicable, and populates it all into $context['ticket_blocks']['tickets'], extending the array that was
 *	already there.
 *
 *	@see shd_main_helpdesk()
 *	@see shd_closed_tickets()
 *	@see shd_recycle_bin()
 *	@since 1.0
*/
function shd_helpdesk_listing()
{
    global $context, $txt, $smcFunc, $user_profile, $scripturl, $settings, $user_info, $modSettings, $language;
    if (!empty($context['shd_permission'])) {
        shd_is_allowed_to($context['shd_permission']);
    }
    $block_list = array_keys($context['ticket_blocks']);
    $primary_url = '?action=helpdesk;sa=' . $_REQUEST['sa'];
    // First figure out the start positions of each item and sanitise them
    foreach ($context['ticket_blocks'] as $block_key => $block) {
        if (empty($block['viewing_as_block'])) {
            $num_per_page = !empty($context['shd_preferences']['blocks_' . $block_key . '_count']) ? $context['shd_preferences']['blocks_' . $block_key . '_count'] : $context['items_per_page'];
            $start = empty($_REQUEST['st_' . $block_key]) ? 0 : (int) $_REQUEST['st_' . $block_key];
            $max_value = $block['count'];
            // easier to read
        } else {
            $num_per_page = $context['items_per_page'];
            $max_value = $context['items_per_page'];
            $start = 0;
        }
        if ($start < 0) {
            $start = 0;
        } elseif ($start >= $max_value) {
            $start = max(0, (int) $max_value - ((int) $max_value % (int) $num_per_page == 0 ? $num_per_page : (int) $max_value % (int) $num_per_page));
        } else {
            $start = max(0, (int) $start - (int) $start % (int) $num_per_page);
        }
        $context['ticket_blocks'][$block_key]['start'] = $start;
        $context['ticket_blocks'][$block_key]['num_per_page'] = $num_per_page;
        if ($start != 0) {
            $_REQUEST['st_' . $block_key] = $start;
        } elseif (isset($_REQUEST['st_' . $block_key])) {
            unset($_REQUEST['st_' . $block_key]);
        }
    }
    // Now ordering the columns, separate loop for breaking the two processes apart
    $sort_methods = array('ticketid' => array('sql' => 'hdt.id_ticket'), 'ticketname' => array('sql' => 'hdt.subject'), 'replies' => array('sql' => 'hdt.num_replies'), 'allreplies' => array('sql' => '(hdt.num_replies + hdt.deleted_replies)'), 'urgency' => array('sql' => 'hdt.urgency'), 'updated' => array('sql' => 'hdt.last_updated'), 'assigned' => array('sql' => 'assigned_name', 'sql_select' => 'IFNULL(mem.real_name, 0) AS assigned_name', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_assigned = mem.id_member)'), 'status' => array('sql' => 'hdt.status'), 'starter' => array('sql' => 'starter_name', 'sql_select' => 'IFNULL(mem.real_name, 0) AS starter_name', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdt.id_member_started = mem.id_member)'), 'lastreply' => array('sql' => 'last_reply', 'sql_select' => 'IFNULL(mem.real_name, 0) AS last_reply', 'sql_join' => 'LEFT JOIN {db_prefix}members AS mem ON (hdtr_last.id_member = mem.id_member)'));
    foreach ($context['ticket_blocks'] as $block_key => $block) {
        $sort = isset($_REQUEST['so_' . $block_key]) ? $_REQUEST['so_' . $block_key] : (!empty($context['shd_preferences']['block_order_' . $block_key . '_block']) ? $context['shd_preferences']['block_order_' . $block_key . '_block'] : '');
        if (strpos($sort, '_') > 0 && substr_count($sort, '_') == 1) {
            list($sort_item, $sort_dir) = explode('_', $sort);
            if (empty($sort_methods[$sort_item])) {
                $sort_item = 'updated';
                $sort = '';
            }
            if (!in_array($sort_dir, array('asc', 'desc'))) {
                $sort = '';
                $sort_dir = 'asc';
            }
        } else {
            $sort = '';
            $sort_item = 'updated';
            $sort_dir = $_REQUEST['sa'] == 'closedtickets' || $_REQUEST['sa'] == 'recyclebin' ? 'desc' : 'asc';
            // default to newest first if on recyclebin or closed tickets, otherwise oldest first
        }
        if ($sort != '') {
            $_REQUEST['so_' . $block_key] = $sort;
        } elseif (isset($_REQUEST['so_' . $block_key])) {
            unset($_REQUEST['so_' . $block_key]);
        }
        $context['ticket_blocks'][$block_key]['sort'] = array('item' => $sort_item, 'direction' => $sort_dir, 'add_link' => $sort != '', 'sql' => array('select' => !empty($sort_methods[$sort_item]['sql_select']) ? $sort_methods[$sort_item]['sql_select'] : '', 'join' => !empty($sort_methods[$sort_item]['sql_join']) ? $sort_methods[$sort_item]['sql_join'] : '', 'sort' => $sort_methods[$sort_item]['sql'] . ' ' . strtoupper($sort_dir)), 'link_bits' => array());
    }
    // Having got all that, step through the blocks again to determine the full URL fragments
    foreach ($context['ticket_blocks'] as $block_key => $block) {
        foreach ($sort_methods as $method => $sort_details) {
            $context['ticket_blocks'][$block_key]['sort']['link_bits'][$method] = ';so_' . $block_key . '=' . $method . '_' . $block['sort']['direction'];
        }
    }
    // Figure out if the user is filtering on anything, and if so, set up containers for the extra joins, selects, pagination link fragments, etc
    $_REQUEST['field'] = isset($_REQUEST['field']) ? (int) $_REQUEST['field'] : 0;
    $_REQUEST['filter'] = isset($_REQUEST['filter']) ? (int) $_REQUEST['filter'] : 0;
    if ($_REQUEST['field'] > 0 && $_REQUEST['filter'] > 0) {
        $context['filter_fragment'] = ';field=' . $_REQUEST['field'] . ';filter=' . $_REQUEST['filter'];
        $context['filter_join'] = '
				INNER JOIN {db_prefix}helpdesk_custom_fields_values AS hdcfv ON (hdcfv.id_post = hdt.id_ticket AND hdcfv.id_field = {int:field} AND hdcfv.post_type = {int:type_ticket})
				INNER JOIN {db_prefix}helpdesk_custom_fields AS hdcf ON (hdcf.id_field = hdcfv.id_field AND hdcf.active = {int:active})';
        $context['filter_where'] = '
				AND hdcfv.value = {string:filter}';
    } else {
        $context['filter_fragment'] = '';
        $context['filter_join'] = '';
        $context['filter_where'] = '';
    }
    // Now go actually do the whole block thang, setting up space for a list of users and tickets as we go along
    $users = array();
    $tickets = array();
    foreach ($context['ticket_blocks'] as $block_key => $block) {
        if (empty($block['display']) || !empty($block['collapsed'])) {
            continue;
        }
        $context['ticket_blocks'][$block_key]['tickets'] = array();
        // If we're filtering, we have to query it first to figure out how many rows there are in this block. It's not pretty.
        if (!empty($context['filter_join'])) {
            $query = shd_db_query('', '
				SELECT COUNT(hdt.id_ticket)
				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)
					INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept)
					' . (!empty($block['sort']['sql']['join']) ? $block['sort']['sql']['join'] : '') . $context['filter_join'] . '
				WHERE {query_see_ticket}' . (!empty($block['where']) ? ' AND ' . $block['where'] : '') . (!empty($context['shd_department']) ? ' AND hdt.id_dept = {int:dept}' : '') . $context['filter_where'], array('dept' => $context['shd_department'], 'user' => $context['user']['id'], 'field' => $_REQUEST['field'], 'filter' => $_REQUEST['filter'], 'type_ticket' => CFIELD_TICKET, 'active' => 1));
            list($context['ticket_blocks'][$block_key]['count']) = $smcFunc['db_fetch_row']($query);
            $block['count'] = $context['ticket_blocks'][$block_key]['count'];
            $smcFunc['db_free_result']($query);
            if ($block['start'] >= $block['count']) {
                $context['ticket_blocks'][$block_key]['start'] = max(0, (int) $block['count'] - ((int) $block['count'] % (int) $block['num_per_page'] == 0 ? $block['num_per_page'] : (int) $block['count'] % (int) $block['num_per_page']));
                $block['start'] = $context['ticket_blocks'][$block_key]['start'];
            }
        }
        $query = shd_db_query('', '
			SELECT hdt.id_ticket, hdt.id_dept, hdd.dept_name, hdt.id_last_msg, hdt.id_member_started, hdt.id_member_updated,
				hdt.id_member_assigned, hdt.subject, hdt.status, hdt.num_replies, hdt.deleted_replies, hdt.private, hdt.urgency,
				hdt.last_updated, hdtr_first.poster_name AS ticket_opener, hdtr_last.poster_name AS respondent, hdtr_last.poster_time,
				IFNULL(hdlr.id_msg, 0) AS log_read' . (!empty($block['sort']['sql']['select']) ? ', ' . $block['sort']['sql']['select'] : '') . '
			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)
				INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept)
				LEFT JOIN {db_prefix}helpdesk_log_read AS hdlr ON (hdt.id_ticket = hdlr.id_ticket AND hdlr.id_member = {int:user})
				' . (!empty($block['sort']['sql']['join']) ? $block['sort']['sql']['join'] : '') . $context['filter_join'] . '
			WHERE {query_see_ticket}' . (!empty($block['where']) ? ' AND ' . $block['where'] : '') . (!empty($context['shd_department']) ? ' AND hdt.id_dept = {int:dept}' : '') . $context['filter_where'] . '
			ORDER BY ' . (!empty($block['sort']['sql']['sort']) ? $block['sort']['sql']['sort'] : 'hdt.id_last_msg ASC') . '
			LIMIT {int:start}, {int:items_per_page}', array('dept' => $context['shd_department'], 'user' => $context['user']['id'], 'start' => $block['start'], 'items_per_page' => $block['num_per_page'], 'field' => $_REQUEST['field'], 'filter' => $_REQUEST['filter'], 'type_ticket' => CFIELD_TICKET, 'active' => 1));
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $is_own = $user_info['id'] == $row['id_member_started'];
            censorText($row['subject']);
            $new_block = array('id' => $row['id_ticket'], 'display_id' => str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT), 'dept_link' => empty($context['shd_department']) && $context['shd_multi_dept'] ? '[<a href="' . $scripturl . '?' . $context['shd_home'] . ';dept=' . $row['id_dept'] . '">' . $row['dept_name'] . '</a>] ' : '', 'link' => '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '">' . $row['subject'] . '</a>', 'subject' => $row['subject'], 'status' => array('level' => $row['status'], 'label' => $txt['shd_status_' . $row['status']]), 'starter' => array('id' => $row['id_member_started'], 'name' => $row['ticket_opener']), 'last_update' => timeformat($row['last_updated']), 'assigned' => array('id' => $row['id_member_assigned']), 'respondent' => array('id' => $row['id_member_updated'], 'name' => $row['respondent']), 'urgency' => array('level' => $row['urgency'], 'label' => $row['urgency'] > TICKET_URGENCY_HIGH ? '<span class="error">' . $txt['shd_urgency_' . $row['urgency']] . '</span>' : $txt['shd_urgency_' . $row['urgency']]), 'is_unread' => $row['id_last_msg'] > $row['log_read'], 'new_href' => $row['id_last_msg'] <= $row['log_read'] ? '' : $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . '.new' . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '#new', 'private' => $row['private'], 'actions' => array('movedept' => !empty($context['shd_multi_dept']) && (shd_allowed_to('shd_move_dept_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_move_dept_own', $context['shd_department'])) ? '<a href="' . $scripturl . '?action=helpdesk;sa=movedept;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_move_dept'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/movedept.png" alt="' . $txt['shd_move_dept'] . '" /></a>' : ''), 'num_replies' => $row['num_replies'], 'replies_href' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $row['id_ticket'] . '.msg' . $row['id_last_msg'] . '#msg' . $row['id_last_msg'] . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : ''), 'all_replies' => (int) $row['num_replies'] + (int) $row['deleted_replies']);
            if ($row['status'] == TICKET_STATUS_CLOSED) {
                $new_block['actions'] += array('resolve' => shd_allowed_to('shd_unresolve_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_unresolve_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_unresolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/unresolved.png" alt="' . $txt['shd_ticket_unresolved'] . '" /></a>' : '');
            } elseif ($row['status'] == TICKET_STATUS_DELETED) {
                $new_block['actions'] += array('restore' => shd_allowed_to('shd_restore_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_restore_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=restoreticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_restore'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/restore.png" alt="' . $txt['shd_ticket_restore'] . '" /></a>' : '', 'permadelete' => shd_allowed_to('shd_delete_recycling', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=permadelete;ticket=' . $row['id_ticket'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_delete_permanently'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_permanently_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_delete_permanently'] . '" /></a>' : '');
            } else {
                $langstring = '';
                if (shd_allowed_to('shd_assign_ticket_any', $context['shd_department'])) {
                    $langstring = empty($row['id_member_assigned']) ? $txt['shd_ticket_assign'] : $txt['shd_ticket_reassign'];
                } elseif (shd_allowed_to('shd_assign_ticket_own', $context['shd_department']) && (empty($row['id_member_assigned']) || $row['id_member_assigned'] == $context['user']['id'])) {
                    $langstring = $row['id_member_assigned'] == $context['user']['id'] ? $txt['shd_ticket_unassign'] : $txt['shd_ticket_assign_self'];
                }
                if (!empty($langstring)) {
                    $new_block['actions']['assign'] = '<a href="' . $scripturl . '?action=helpdesk;sa=assign;ticket=' . $row['id_ticket'] . ';home;' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $langstring . '"><img src="' . $settings['default_images_url'] . '/simpledesk/assign.png" alt="' . $langstring . '" /></a>';
                }
                $new_block['actions'] += array('resolve' => shd_allowed_to('shd_resolve_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_resolve_ticket_own', $context['shd_department']) ? '<a href="' . $scripturl . '?action=helpdesk;sa=resolveticket;ticket=' . $row['id_ticket'] . ';home;' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_resolved'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/resolved.png" alt="' . $txt['shd_ticket_resolved'] . '" /></a>' : '', 'tickettotopic' => empty($modSettings['shd_helpdesk_only']) && shd_allowed_to('shd_ticket_to_topic', $context['shd_department']) && ($row['deleted_replies'] == 0 || shd_allowed_to('shd_access_recyclebin')) ? '<a href="' . $scripturl . '?action=helpdesk;sa=tickettotopic;ticket=' . $row['id_ticket'] . ';' . $context['shd_dept_link'] . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_move_to_topic'] . '"><img src="' . $settings['default_images_url'] . '/simpledesk/tickettotopic.png" alt="' . $txt['shd_ticket_move_to_topic'] . '" /></a>' : '', 'delete' => shd_allowed_to('shd_delete_ticket_any', $context['shd_department']) || $is_own && shd_allowed_to('shd_delete_ticket_own') ? '<a href="' . $scripturl . '?action=helpdesk;sa=deleteticket;ticket=' . $row['id_ticket'] . ';' . $context['shd_dept_link'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '" title="' . $txt['shd_ticket_delete'] . '" onclick="return confirm(' . JavaScriptEscape($txt['shd_delete_confirm']) . ');"><img src="' . $settings['default_images_url'] . '/simpledesk/delete.png" alt="' . $txt['shd_ticket_delete'] . '" /></a>' : '');
            }
            $context['ticket_blocks'][$block_key]['tickets'][$row['id_ticket']] = $new_block;
            $users[] = $row['id_member_started'];
            $users[] = $row['id_member_updated'];
            $users[] = $row['id_member_assigned'];
            $tickets[$row['id_ticket']] = array();
        }
        $smcFunc['db_free_result']($query);
    }
    $users = array_unique($users);
    if (!empty($users)) {
        loadMemberData($users, false, 'minimal');
    }
    foreach ($context['ticket_blocks'] as $block_id => $block) {
        if (empty($block['tickets'])) {
            continue;
        }
        foreach ($block['tickets'] as $tid => $ticket) {
            // Set up names and profile links for topic starter
            if (!empty($user_profile[$ticket['starter']['id']])) {
                // We found the name, so let's use their current name and profile link
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name'] = $user_profile[$ticket['starter']['id']]['real_name'];
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = shd_profile_link($user_profile[$ticket['starter']['id']]['real_name'], $ticket['starter']['id']);
            } else {
                // We didn't, so keep using the name we found previously and don't make an actual link
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['starter']['name'];
            }
            // Set up names and profile links for assigned user
            if ($ticket['assigned']['id'] == 0 || empty($user_profile[$ticket['assigned']['id']])) {
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $txt['shd_unassigned'];
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = '<span class="error">' . $txt['shd_unassigned'] . '</span>';
            } else {
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['name'] = $user_profile[$ticket['assigned']['id']]['real_name'];
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['assigned']['link'] = shd_profile_link($user_profile[$ticket['assigned']['id']]['real_name'], $ticket['assigned']['id']);
            }
            // And last respondent
            if ($ticket['respondent']['id'] == 0 || empty($user_profile[$ticket['respondent']['id']])) {
                // Didn't find the name, so reuse what we have
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name'];
            } else {
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['name'] = $user_profile[$ticket['respondent']['id']]['real_name'];
                $context['ticket_blocks'][$block_id]['tickets'][$tid]['respondent']['link'] = shd_profile_link($user_profile[$ticket['respondent']['id']]['real_name'], $ticket['respondent']['id']);
            }
        }
    }
    foreach ($context['ticket_blocks'] as $block_id => $block) {
        if (empty($block['display']) || empty($block['count']) && !$block['required'] && empty($block['collapsed'])) {
            unset($context['ticket_blocks'][$block_id]);
        }
    }
    $base_url = '';
    foreach ($context['ticket_blocks'] as $block_id => $block) {
        if ($block['sort']['add_link']) {
            $base_url .= $block['sort']['link_bits'][$block['sort']['item']];
        }
    }
    if ($_REQUEST['sa'] != 'viewblock') {
        foreach ($context['ticket_blocks'] as $block_id => $block) {
            $num_per_page = !empty($context['shd_preferences']['blocks_' . $block_key . '_count']) ? $context['shd_preferences']['blocks_' . $block_key . '_count'] : $context['items_per_page'];
            $url_fragment = $base_url;
            foreach ($block_list as $block_item) {
                if ($block_item == $block_id) {
                    $url_fragment .= ';st_' . $block_item . '=%1$d';
                } elseif (!empty($context['ticket_blocks'][$block_item]['start'])) {
                    $url_fragment .= ';st_' . $block_item . '=' . $context['ticket_blocks'][$block_item]['start'];
                }
            }
            $context['start'] = $context['ticket_blocks'][$block_id]['start'];
            $context['ticket_blocks'][$block_id]['page_index'] = shd_no_expand_pageindex($scripturl . $primary_url . $url_fragment . $context['shd_dept_link'] . $context['filter_fragment'] . '#shd_block_' . $block_id, $context['start'], $block['count'], $block['num_per_page'], true);
        }
    }
    // Just need to deal with those pesky prefix fields, if there are any.
    if (empty($tickets)) {
        return;
    }
    // We're all done here.
    // 1. Figure out if there are any custom fields that apply to us or not.
    if ($context['shd_multi_dept'] && empty($context['shd_department'])) {
        $dept_list = shd_allowed_to('access_helpdesk', false);
    } else {
        $dept_list = array($context['shd_department']);
    }
    $fields = array();
    $query = $smcFunc['db_query']('', '
		SELECT hdcf.id_field, can_see, field_type, field_options, placement, field_name
		FROM {db_prefix}helpdesk_custom_fields AS hdcf
			INNER JOIN {db_prefix}helpdesk_custom_fields_depts AS hdcfd ON (hdcfd.id_field = hdcf.id_field)
		WHERE placement IN ({array_int:placement_prefix})
			AND field_loc IN ({array_int:locations})
			AND hdcfd.id_dept IN ({array_int:dept_list})
			AND active = {int:active}
		GROUP BY hdcf.id_field
		ORDER BY field_order', array('locations' => array(CFIELD_TICKET, CFIELD_TICKET | CFIELD_REPLY), 'placement_prefix' => array(CFIELD_PLACE_PREFIX, CFIELD_PLACE_PREFIXFILTER), 'active' => 1, 'dept_list' => $dept_list));
    $is_staff = shd_allowed_to('shd_staff', $context['shd_department']);
    $is_admin = $context['user']['is_admin'] || shd_allowed_to('admin_helpdesk', $context['shd_department']);
    $context['shd_filter_fields'] = array();
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        list($user_see, $staff_see) = explode(',', $row['can_see']);
        if ($is_admin || $is_staff && $staff_see == '1' || !$is_staff && $user_see == '1') {
            if (!empty($row['field_options'])) {
                $row['field_options'] = unserialize($row['field_options']);
                if (isset($row['field_options']['inactive'])) {
                    unset($row['field_options']['inactive']);
                }
                foreach ($row['field_options'] as $k => $v) {
                    if (strpos($v, '[') !== false) {
                        $row['field_options'][$k] = parse_bbc($v);
                    }
                }
            }
            $fields[$row['id_field']] = $row;
            if ($row['placement'] == CFIELD_PLACE_PREFIXFILTER) {
                $context['shd_filter_fields'][$row['id_field']] = array('name' => $row['field_name'], 'options' => $row['field_options'], 'in_use' => array());
            }
        }
    }
    $smcFunc['db_free_result']($query);
    if (empty($fields)) {
        return;
    }
    // No fields to process, time to go.
    // 2. Get the relevant values.
    $query = $smcFunc['db_query']('', '
		SELECT id_post, id_field, value
		FROM {db_prefix}helpdesk_custom_fields_values
		WHERE id_post IN ({array_int:tickets})
			AND id_field IN ({array_int:fields})
			AND post_type = {int:ticket}', array('tickets' => array_keys($tickets), 'fields' => array_keys($fields), 'ticket' => CFIELD_TICKET));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        $tickets[$row['id_post']][$row['id_field']] = $row['value'];
    }
    // 3. Apply the values into the tickets.
    if ($_REQUEST['sa'] == 'closedtickets') {
        $context['filterbase'] = $scripturl . '?action=helpdesk;sa=closedtickets';
    } elseif ($_REQUEST['sa'] == 'recyclebin') {
        $context['filterbase'] = $scripturl . '?action=helpdesk;sa=recyclebin';
    } else {
        $context['filterbase'] = $scripturl . '?' . $context['shd_home'];
    }
    foreach ($context['ticket_blocks'] as $block_id => $block) {
        if (empty($block['tickets'])) {
            continue;
        }
        foreach ($block['tickets'] as $ticket_id => $ticket) {
            if (isset($tickets[$ticket_id])) {
                $prefix_filter = '';
                $prefix = '';
                foreach ($fields as $field_id => $field) {
                    if (empty($tickets[$ticket_id][$field_id])) {
                        continue;
                    }
                    if ($field['placement'] == CFIELD_PLACE_PREFIXFILTER) {
                        if (!isset($field['field_options'][$tickets[$ticket_id][$field_id]])) {
                            continue;
                        }
                        $prefix_filter .= '[<a href="' . $context['filterbase'] . $context['shd_dept_link'] . ';field=' . $field_id . ';filter=' . $tickets[$ticket_id][$field_id] . '">' . $field['field_options'][$tickets[$ticket_id][$field_id]] . '</a>] ';
                    } else {
                        if ($field['field_type'] == CFIELD_TYPE_CHECKBOX) {
                            $prefix .= !empty($tickets[$ticket_id][$field_id]) ? $txt['yes'] . ' ' : $txt['no'] . ' ';
                        } elseif ($field['field_type'] == CFIELD_TYPE_SELECT || $field['field_type'] == CFIELD_TYPE_RADIO) {
                            $prefix .= $field['field_options'][$tickets[$ticket_id][$field_id]] . ' ';
                        } elseif ($field['field_type'] == CFIELD_TYPE_MULTI) {
                            $values = explode(',', $tickets[$ticket_id][$field_id]);
                            foreach ($values as $value) {
                                $prefix .= $field['field_options'][$value] . ' ';
                            }
                        } else {
                            $prefix .= $tickets[$ticket_id][$field_id] . ' ';
                        }
                    }
                }
                // First, set aside the subject, and if there is a non category prefix, strip links from it.
                $subject = $ticket['subject'];
                if (!empty($prefix)) {
                    $prefix = '[' . trim(preg_replace('~<a (.*?)</a>~is', '', $prefix)) . '] ';
                }
                // Then, if we have a category prefix, prepend that to any other prefix we have.
                if (!empty($prefix_filter)) {
                    $prefix = $prefix_filter . $prefix;
                }
                // Lastly, if we have some kind of prefix to put in front of this ticket, do so.
                if (!empty($prefix)) {
                    $context['ticket_blocks'][$block_id]['tickets'][$ticket_id]['subject'] = $prefix . $subject;
                    $context['ticket_blocks'][$block_id]['tickets'][$ticket_id]['link'] = $prefix . '<a href="' . $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket_id . ($_REQUEST['sa'] == 'recyclebin' ? ';recycle' : '') . '">' . $subject . '</a>';
                }
            }
        }
    }
    // 4. We've collected the list of prefix-filter fields in use, now establish which values are actually in use.
    if (!empty($context['shd_filter_fields'])) {
        $query = $smcFunc['db_query']('', '
			SELECT id_field, value
			FROM {db_prefix}helpdesk_custom_fields_values
			WHERE id_field IN ({array_int:fields})', array('fields' => array_keys($context['shd_filter_fields'])));
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $context['shd_filter_fields'][$row['id_field']]['in_use'][$row['value']] = true;
        }
        $smcFunc['db_free_result']($query);
        foreach ($context['shd_filter_fields'] as $id_field => $field) {
            if (empty($field['in_use'])) {
                unset($context['shd_filter_fields'][$id_field]);
            } else {
                foreach ($field['options'] as $k => $v) {
                    if (!isset($field['in_use'][$k])) {
                        unset($context['shd_filter_fields'][$id_field]['options'][$k]);
                    }
                }
                if (empty($context['shd_filter_fields'][$id_field]['options'])) {
                    unset($context['shd_filter_fields'][$id_field]);
                }
            }
        }
    }
}
function shd_add_to_boardindex(&$boardIndexOptions, &$categories)
{
    global $context, $modSettings, $smcFunc, $board, $txt, $scripturl, $settings;
    // Does the category exist? If it has no boards, it actually might not exist, daft as it sounds.
    // But it's more tricky than that, too! We need to be at the board index, not in a child board.
    if (!empty($board)) {
        return;
    }
    call_integration_hook('shd_hook_boardindex_before', array(&$boardIndexOptions, &$categories));
    // OK, so what helpdesks are we displaying?
    $depts = shd_allowed_to('access_helpdesk', false);
    if (empty($depts)) {
        return;
    }
    $cat_list = array();
    $query = $smcFunc['db_query']('', '
		SELECT id_dept, dept_name, description, board_cat, before_after
		FROM {db_prefix}helpdesk_depts
		WHERE id_dept IN ({array_int:depts})
		ORDER BY before_after DESC, dept_order', array('depts' => $depts));
    $depts = array_flip($depts);
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        if ($row['board_cat'] == 0) {
            unset($depts[$row['id_dept']]);
            continue;
        }
        $depts[$row['id_dept']] = $row;
        $cat_list[] = $row['board_cat'];
        $context['dept_list'][$row['id_dept']] = array('id_dept' => $row['id_dept'], 'dept_name' => $row['dept_name'], 'dept_desc' => $row['description'], 'tickets' => array('open' => 0, 'closed' => 0, 'assigned' => 0), 'new' => false);
    }
    if (empty($context['dept_list'])) {
        return;
    }
    $cat_list = array_unique($cat_list);
    // Do we have all these categories?
    foreach ($cat_list as $k => $v) {
        if (!empty($categories[$v])) {
            unset($cat_list[$k]);
        }
    }
    if (!empty($cat_list)) {
        // Uh oh, we have to load a category or two.
        $new_cats = array();
        $request = $smcFunc['db_query']('', '
			SELECT c.id_cat, c.name, c.can_collapse, IFNULL(cc.id_member, 0) AS is_collapsed
			FROM {db_prefix}categories AS c
				LEFT JOIN {db_prefix}collapsed_categories AS cc ON (cc.id_cat = c.id_cat AND cc.id_member = {int:current_member})
			WHERE c.id_cat IN ({array_int:cat})', array('cat' => $cat_list, 'current_member' => $context['user']['id']));
        while ($this_cat = $smcFunc['db_fetch_assoc']($request)) {
            $new_cats[$this_cat['id_cat']] = array('id' => $this_cat['id_cat'], 'name' => $this_cat['name'], 'is_collapsed' => isset($this_cat['can_collapse']) && $this_cat['can_collapse'] == 1 && $this_cat['is_collapsed'] > 0, 'can_collapse' => isset($this_cat['can_collapse']) && $this_cat['can_collapse'] == 1, 'collapse_href' => isset($this_cat['can_collapse']) ? $scripturl . '?action=collapse;c=' . $this_cat['id_cat'] . ';sa=' . ($this_cat['is_collapsed'] > 0 ? 'expand;' : 'collapse;') . $context['session_var'] . '=' . $context['session_id'] . '#c' . $this_cat['id_cat'] : '', 'collapse_image' => isset($this_cat['can_collapse']) ? '<img src="' . $settings['images_url'] . '/' . ($this_cat['is_collapsed'] > 0 ? 'expand.png" alt="+"' : 'collapse.png" alt="-"') . ' />' : '', 'href' => $scripturl . '#c' . $this_cat['id_cat'], 'boards' => array(), 'new' => false);
            $new_cats[$this_cat['id_cat']]['link'] = '<a id="c' . $this_cat['id_cat'] . '" href="' . (isset($this_cat['can_collapse']) ? $new_cats[$this_cat['id_cat']]['collapse_href'] : $new_cats[$this_cat['id_cat']]['href']) . '">' . $this_cat['name'] . '</a>';
        }
        $smcFunc['db_free_result']($request);
        // So, did we add any new categories? If we didn't, something's wrong - abort safely NOW.
        if (empty($new_cats)) {
            return;
        }
        // OK, so we have some categories to integrate.
        $old_cats = $categories;
        $categories = array();
        $request = $smcFunc['db_query']('', '
			SELECT id_cat
			FROM {db_prefix}categories
			ORDER BY cat_order');
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            if (isset($old_cats[$row['id_cat']])) {
                $categories[$row['id_cat']] = $old_cats[$row['id_cat']];
            } elseif (isset($new_cats[$row['id_cat']])) {
                $categories[$row['id_cat']] = $new_cats[$row['id_cat']];
            }
        }
        $smcFunc['db_free_result']($request);
    }
    // So, OK, the categories exist. Now we need to create our magic boards, and integrate them.
    // First we do the after's, in order.
    foreach ($depts as $dept) {
        if (empty($dept['before_after'])) {
            continue;
        }
        $dept['link'] = count($depts) != 0 ? ';dept=' . $dept['id_dept'] : '';
        $new_board = shd_dept_board($dept);
        $categories[$dept['board_cat']]['boards'][$new_board['id']] = $new_board;
    }
    // OK, now for the before's. Because we're merging, that means we're doing them last-first.
    $depts = array_reverse($depts);
    foreach ($depts as $dept) {
        if (!empty($dept['before_after'])) {
            continue;
        }
        $dept['link'] = count($depts) != 0 ? ';dept=' . $dept['id_dept'] : '';
        $new_board = shd_dept_board($dept);
        $categories[$dept['board_cat']]['boards'] = array_merge(array($new_board['id'] => $new_board), $categories[$dept['board_cat']]['boards']);
    }
    // Last but not least, fix up the replacements and some figuring out.
    shd_get_ticket_counts();
    shd_get_unread_departments();
    if (empty($context['shd_buffer_preg_replacements'])) {
        $context['shd_buffer_preg_replacements'] = array();
    }
    foreach ($context['dept_list'] as $dept => $dept_details) {
        // Inject the count of tickets.
        $dept_id = '~' . preg_quote(comma_format(-$dept), '~') . '\\s+' . preg_quote($txt['redirects'], '~') . '~';
        $context['shd_buffer_preg_replacements'][$dept_id] = $dept_details['tickets']['open'] . ' ' . ($dept_details['tickets']['open'] == 1 ? $txt['shd_open_ticket'] : $txt['shd_open_tickets']);
    }
    // Call the relevant function via hook.
    add_integration_function('shd_hook_buffer', 'shd_buffer_boardindex', false);
    call_integration_hook('shd_hook_boardindex_after', array(&$categories));
}
Ejemplo n.º 5
0
/**
 *	Loads the possible permutations of canned replies.
 *
 *	@since 2.0
*/
function shd_load_canned_replies()
{
    global $context, $smcFunc, $user_info;
    if ($context['user']['is_admin'] || shd_allowed_to('admin_helpdesk', $context['shd_department'])) {
        $visible = '';
    } elseif (shd_allowed_to('shd_staff', $context['shd_department'])) {
        $visible = '
			AND hdcr.vis_staff = 1';
    } else {
        $visible = '
			AND hdcr.vis_user = 1';
    }
    $context['canned_replies'] = array();
    $query = $smcFunc['db_query']('', '
		SELECT hdcr.id_reply, hdcr.title, hdcrc.id_cat, hdcrc.cat_name
		FROM {db_prefix}helpdesk_cannedreplies AS hdcr
			INNER JOIN {db_prefix}helpdesk_cannedreplies_cats AS hdcrc ON (hdcr.id_cat = hdcrc.id_cat)
			INNER JOIN {db_prefix}helpdesk_cannedreplies_depts AS hdcrd ON (hdcrd.id_reply = hdcr.id_reply)
		WHERE hdcrd.id_dept = {int:dept}
			AND hdcr.active = 1' . $visible . '
		ORDER BY hdcrc.cat_order, hdcr.reply_order', array('dept' => $context['shd_department']));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        if (!isset($context['canned_replies'][$row['id_cat']])) {
            $context['canned_replies'][$row['id_cat']] = array('name' => $row['cat_name'], 'replies' => array());
        }
        $context['canned_replies'][$row['id_cat']]['replies'][$row['id_reply']] = $row['title'];
    }
}
Ejemplo n.º 6
0
function shd_attachment_info($attach_info)
{
    global $scripturl, $context, $modSettings, $txt, $sourcedir, $smcFunc;
    $filename = preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attach_info['filename']));
    $deleteable = shd_allowed_to('shd_delete_attachment', $context['ticket']['dept']);
    $attach = array('id' => $attach_info['id_attach'], 'name' => $filename, 'size' => round($attach_info['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attach_info['filesize'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'], 'link' => shd_attach_icon($filename) . '&nbsp;<a href="' . $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'] . '">' . htmlspecialchars($attach_info['filename']) . '</a>', 'is_image' => !empty($modSettings['attachmentShowImages']) && !empty($attach_info['width']) && !empty($attach_info['height']), 'can_delete' => $deleteable);
    if ($attach['is_image']) {
        $attach += array('real_width' => $attach_info['width'], 'width' => $attach_info['width'], 'real_height' => $attach_info['height'], 'height' => $attach_info['height']);
        // Let's see, do we want thumbs?
        if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attach_info['width'] > $modSettings['attachmentThumbWidth'] || $attach_info['height'] > $modSettings['attachmentThumbHeight']) && strlen($attach_info['filename']) < 249) {
            // A proper thumb doesn't exist yet? Create one!
            if (empty($attach_info['id_thumb']) || $attach_info['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attach_info['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attach_info['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attach_info['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                $filename = getAttachmentFilename($attach_info['filename'], $attach_info['id_attach'], $attach_info['id_folder']);
                require_once $sourcedir . '/Subs-Graphics.php';
                if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                    // So what folder are we putting this image in?
                    if (!empty($modSettings['currentAttachmentUploadDir'])) {
                        if (!is_array($modSettings['attachmentUploadDir'])) {
                            $modSettings['attachmentUploadDir'] = json_decode($modSettings['attachmentUploadDir'], true);
                        }
                        $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                        $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                    } else {
                        $path = $modSettings['attachmentUploadDir'];
                        $id_folder_thumb = 1;
                    }
                    // Calculate the size of the created thumbnail.
                    $size = @getimagesize($filename . '_thumb');
                    list($attach_info['thumb_width'], $attach_info['thumb_height']) = $size;
                    $thumb_size = filesize($filename . '_thumb');
                    // These are the only valid image types for SMF.
                    $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
                    // What about the extension?
                    $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                    // Figure out the mime type.
                    if (!empty($size['mime'])) {
                        $thumb_mime = $size['mime'];
                    } else {
                        $thumb_mime = 'image/' . $thumb_ext;
                    }
                    $thumb_filename = $attach_info['filename'] . '_thumb';
                    $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                    // Add this beauty to the database.
                    $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, 0, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attach_info['thumb_width'], (int) $attach_info['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                    $old_id_thumb = $attach_info['id_thumb'];
                    $attach_info['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                    if (!empty($attach_info['id_thumb'])) {
                        // Update the tables to notify that we has us a thumbnail
                        $smcFunc['db_query']('', '
							UPDATE {db_prefix}attachments
							SET id_thumb = {int:id_thumb}
							WHERE id_attach = {int:id_attach}', array('id_thumb' => $attach_info['id_thumb'], 'id_attach' => $attach_info['id_attach']));
                        $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int'), array($attach_info['id_thumb'], $attach_info['id_ticket'], $attach_info['id_msg']), array('id_attach'));
                        $thumb_realname = getAttachmentFilename($thumb_filename, $attach_info['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                        rename($filename . '_thumb', $thumb_realname);
                        // Do we need to remove an old thumbnail?
                        if (!empty($old_id_thumb)) {
                            require_once $sourcedir . '/ManageAttachments.php';
                            removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                        }
                    }
                }
            }
            // Only adjust dimensions on successful thumbnail creation.
            if (!empty($attach_info['thumb_width']) && !empty($attach_info['thumb_height'])) {
                $attach['width'] = $attach_info['thumb_width'];
                $attach['height'] = $attach_info['thumb_height'];
            }
        }
        if (!empty($attach_info['id_thumb'])) {
            $attach['thumbnail'] = array('id' => $attach_info['id_thumb'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_thumb'] . ';image');
        }
        $attach['thumbnail']['has_thumb'] = !empty($attach_info['id_thumb']);
        // If thumbnails are disabled, check the maximum size of the image.
        if (!$attach['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attach_info['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attach_info['height'] > $modSettings['max_image_height'])) {
            if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width'] <= $modSettings['max_image_height'])) {
                $attach['width'] = $modSettings['max_image_width'];
                $attach['height'] = floor($attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width']);
            } elseif (!empty($modSettings['max_image_width'])) {
                $attach['width'] = floor($attach['width'] * $modSettings['max_image_height'] / $attach['height']);
                $attach['height'] = $modSettings['max_image_height'];
            }
        } elseif ($attach['thumbnail']['has_thumb']) {
            // Make it a popup (since invariably it'll break the layout otherwise)
            $attach['thumbnail']['javascript'] = 'return reqWin(\'' . $attach['href'] . ';image\', ' . ($attach_info['width'] + 20) . ', ' . ($attach_info['height'] + 20) . ', true);';
        }
    }
    return $attach;
}
Ejemplo n.º 7
0
function shd_get_postable_depts()
{
    global $context, $smcFunc;
    $depts = shd_allowed_to('shd_new_ticket', false);
    $context['postable_dept_list'] = array();
    $context['ticket_form']['custom_field_dept'] = 0;
    if (!empty($depts)) {
        $query = $smcFunc['db_query']('', '
			SELECT id_dept, dept_name
			FROM {db_prefix}helpdesk_depts
			WHERE id_dept IN ({array_int:depts})
			ORDER BY dept_order', array('depts' => $depts));
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $context['postable_dept_list'][$row['id_dept']] = $row['dept_name'];
        }
        $smcFunc['db_free_result']($query);
        // We do actually need to get the first one for the purposes of custom fields. But only the first one.
        foreach ($context['postable_dept_list'] as $id => $dept) {
            $context['ticket_form']['custom_field_dept'] = $id;
            break;
        }
    }
}
Ejemplo n.º 8
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]();
}
/**
 *	Displays the list of possible searching criteria.
 *
 *	@see shd_search()
 *	@since 2.0
*/
function template_search()
{
    global $context, $txt, $scripturl, $settings, $modSettings;
    // Back to the helpdesk.
    echo '
		<div class="floatleft">
			', template_button_strip(array($context['navigation']['back']), 'bottom'), '
		</div><br class="clear" /><br />';
    if (!empty($modSettings['shd_new_search_index'])) {
        echo '
	<div class="errorbox"><img src="', $settings['default_images_url'], '/simpledesk/warning.png" alt="*" class="shd_icon_minihead" /> &nbsp;', shd_allowed_to('admin_helpdesk', 0) ? $txt['shd_search_warning_admin'] : $txt['shd_search_warning_nonadmin'], '</div>';
    }
    echo '
	<div class="cat_bar">
		<h3 class="catbg">
			<img src="', $settings['default_images_url'], '/simpledesk/search.png" alt="*" />
			', $txt['shd_search'], '
		</h3>
	</div>
	<div class="roundframe">
		<form action="', $scripturl, '?action=helpdesk;sa=search2" method="post">
			<div class="content">
				<br />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_text'], '</strong>
					</dt>
					<dd>
						<input type="text" name="search" value="" size="40" maxlength="100" class="input_text" />
					</dd>
					<dt>
						<strong>', $txt['shd_search_match'], '</strong>
					</dt>
					<dd>
						<select name="searchtype">
							<option value="all">', $txt['shd_search_match_all'], '</option>
							<option value="any">', $txt['shd_search_match_any'], '</option>
						</select>
					</dd>
				</dl>
				<br />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_where'], '</strong>
					</dt>
					<dd>
						<input type="checkbox" class="input_check" checked="checked" name="search_subjects" /> ', $txt['shd_search_where_subjects'], '<br />
						<input type="checkbox" class="input_check" checked="checked" name="search_tickets" /> ', $txt['shd_search_where_tickets'], '<br />
						<input type="checkbox" class="input_check" checked="checked" name="search_replies" /> ', $txt['shd_search_where_replies'], '<br />
					</dd>
				</dl>';
    if (count($context['dept_list']) == 1) {
        $array = array_keys($context['dept_list']);
        echo '
					<input type="hidden" name="search_dept[]" value="', $array[0], '" />';
    } else {
        echo '
				<hr />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_dept'], '</strong>
					</dt>
					<dd>';
        foreach ($context['dept_list'] as $id => $name) {
            echo '
							<input type="checkbox" class="input_check" checked="checked" name="search_dept[]" value="', $id, '" /> &nbsp;', $name, '<br />';
        }
        echo '
					</dd>
				</dl>';
    }
    echo '
				<hr />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_scope'], '</strong>
					</dt>
					<dd>
						<input type="checkbox" class="input_check" checked="checked" name="scope_open" /> &nbsp;', $txt['shd_search_scope_open'], '<br />
						<input type="checkbox" class="input_check" checked="checked" name="scope_closed" /> &nbsp;', $txt['shd_search_scope_closed'], '<br />
						<input type="checkbox" class="input_check" checked="checked" name="scope_recycle" /> &nbsp;', $txt['shd_search_scope_recycle'], '<br />
					</dd>
				</dl>
				<hr />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_urgency'], '</strong>
					</dt>
					<dd>';
    // All the urgency levels, currently 0-5.
    for ($i = 0; $i <= 5; $i++) {
        echo '
						<input type="checkbox" class="input_check" checked="checked" name="urgency[]" value="', $i, '" /> &nbsp;', $txt['shd_urgency_' . $i], '<br />';
    }
    echo '
					</dd>
				</dl>
				<hr />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_ticket_starter'], '</strong>
						<div class="smalltext">', $txt['shd_search_ticket_named_person'], '</div>
					</dt>
					<dd>
						<input type="hidden" name="starter" value="" />
						<input type="text" name="starter_name" id="starter_name" size="40" maxlength="100" class="input_text" value="" />
						<div id="starter_name_container"></div>
					</dd>
				</dl>
				<br />
				<dl class="settings">
					<dt>
						<strong>', $txt['shd_search_ticket_assignee'], '</strong>
						<div class="smalltext">', $txt['shd_search_ticket_named_person'], '</div>
					</dt>
					<dd>
						<input type="hidden" name="assignee" value="" />
						<input type="text" name="assignee_name" id="assignee_name" size="40" maxlength="100" class="input_text" value="" />
						<div id="assignee_name_container"></div>
					</dd>
				</dl>

				<script type="text/javascript" src="', $settings['default_theme_url'], '/scripts/suggest.js?20fin"></script>
				<script type="text/javascript"><!-- // --><![CDATA[
					var oTicketStarter = new smc_AutoSuggest({
						sSelf: \'oTicketStarter\',
						sSessionId: \'', $context['session_id'], '\',
						sSessionVar: \'', $context['session_var'], '\',
						sControlId: \'starter_name\',
						sSuggestId: \'starter\',
						sSearchType: \'member\',
						sPostName: \'starter_name_form\',
						sURLMask: \'action=profile;u=%item_id%\',
						bItemList: true,
						sItemListContainerId: \'starter_name_container\',
						aListItems: []
					});
					var oTicketAssignee = new smc_AutoSuggest({
						sSelf: \'oTicketAssignee\',
						sSessionId: \'', $context['session_id'], '\',
						sSessionVar: \'', $context['session_var'], '\',
						sControlId: \'assignee_name\',
						sSuggestId: \'assignee\',
						sSearchType: \'member\',
						sPostName: \'assigned_name_form\',
						sURLMask: \'action=profile;u=%item_id%\',
						bItemList: true,
						sItemListContainerId: \'assignee_name_container\',
						aListItems: []
					});
				// ]', ']></script>
				<hr />
				<br />
				<input type="submit" value="', $txt['shd_search'], '" onclick="return submitThisOnce(this);" accesskey="s" class="button_submit" />
			</div>
		</form>
	</div>
	<span class="lowerframe"><span></span></span>';
}
Ejemplo n.º 10
0
/**
 *	Handles the actual assignment form, validates it and carries it out.
 *
 *	Primarily this is just about receiving the form, making the same checks that {@link shd_movedept()} does and then
 *	logging the action before updating the database.
 *
 *	@see shd_movedept()
 *	@since 2.0
*/
function shd_movedept2()
{
    global $context, $smcFunc, $user_info, $sourcedir, $txt, $scripturl;
    checkSession();
    checkSubmitOnce('check');
    if (empty($context['ticket_id'])) {
        fatal_lang_error('shd_no_ticket', false);
    }
    if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '') && (empty($modSettings['shd_helpdesk_only']) || empty($modSettings['shd_disable_pm']))) {
        fatal_lang_error('shd_move_no_pm', false);
    }
    // Just in case, are they cancelling?
    if (isset($_REQUEST['cancel'])) {
        redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
    }
    if (empty($context['shd_multi_dept'])) {
        fatal_lang_error('shd_cannot_move_dept', false);
    }
    $dest = isset($_REQUEST['to_dept']) ? (int) $_REQUEST['to_dept'] : 0;
    if (empty($dest) || !shd_allowed_to('access_helpdesk', $dest)) {
        fatal_lang_error('shd_cannot_move_dept', false);
    }
    $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket';
    // Get ticket details - and kick it out if they shouldn't be able to see it.
    $query = shd_db_query('', '
		SELECT id_member_started, subject, hdt.id_dept, dept_name
		FROM {db_prefix}helpdesk_tickets AS hdt
			INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept)
		WHERE {query_see_ticket} AND id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
    $log_params = array();
    if ($row = $smcFunc['db_fetch_row']($query)) {
        list($ticket_starter, $subject, $context['current_dept'], $context['current_dept_name']) = $row;
    } else {
        $smcFunc['db_free_result']($query);
        fatal_lang_error('shd_no_ticket');
    }
    $smcFunc['db_free_result']($query);
    if ($context['current_dept'] == $dest) {
        fatal_lang_error('shd_cannot_move_dept', false);
    }
    if (shd_allowed_to('shd_move_dept_any', $context['current_dept']) || shd_allowed_to('shd_move_dept_own', $context['current_dept']) && $ticket_starter == $user_info['id']) {
        // Find the new department. We've already established the user can see it, but we need its name.
        $query = $smcFunc['db_query']('', '
			SELECT id_dept, dept_name
			FROM {db_prefix}helpdesk_depts
			WHERE id_dept IN ({int:dest})', array('dest' => $dest));
        list($new_dept, $dept_name) = $smcFunc['db_fetch_row']($query);
        $smcFunc['db_free_result']($query);
        // Just before we move, call any interesting hooks. We do normally have a lot of fun staff in $context and $_POST, but the department ID and name aren't in either.
        call_integration_hook('shd_hook_movedept', array(&$new_dept, &$dept_name));
        $log_params = array('subject' => $subject, 'ticket' => $context['ticket_id'], 'old_dept_id' => $context['current_dept'], 'old_dept_name' => $context['current_dept_name'], 'new_dept_id' => $new_dept, 'new_dept_name' => $dept_name);
        shd_log_action('move_dept', $log_params);
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}helpdesk_tickets
			SET id_dept = {int:new_dept}
			WHERE id_ticket = {int:ticket}', array('new_dept' => $new_dept, 'ticket' => $context['ticket_id']));
        // Now, notify the ticket starter if that's what we wanted to do.
        if (isset($_POST['send_pm'])) {
            require_once $sourcedir . '/Subs-Post.php';
            $request = shd_db_query('pm_find_username', '
				SELECT id_member, real_name
				FROM {db_prefix}members
				WHERE id_member = {int:user}
				LIMIT 1', array('user' => $ticket_starter));
            list($userid, $username) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
            // Fix the content
            $replacements = array('{user}' => $username, '{subject}' => $subject, '{current_dept}' => $context['current_dept_name'], '{new_dept}' => $dept_name, '{link}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
            $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']);
            $recipients = array('to' => array($ticket_starter), 'bcc' => array());
            sendpm($recipients, $txt['shd_ticket_moved_subject'], un_htmlspecialchars($message));
        }
        shd_clear_active_tickets($context['current_dept']);
        shd_clear_active_tickets($new_dept);
        if (!empty($context['shd_return_to']) && $context['shd_return_to'] == 'home') {
            redirectexit($context['shd_home'] . ';dept=' . $new_dept);
        } else {
            redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
        }
    } else {
        fatal_lang_error('shd_no_perm_move_dept', false);
    }
}
Ejemplo n.º 11
0
/**
 *	Perform all the operations required for SimpleDesk to safely start operations inside the admin panel.
 *
 *	@param array &$admin_areas The full admin area array from SMF's Admin.php.
 *	@since 2.0
*/
function shd_admin_bootstrap(&$admin_areas)
{
    global $sourcedir, $modSettings, $txt, $context, $scripturl;
    // Load the main admin language files and any needed for SD plugins in the admin panel.
    require_once $sourcedir . '/sd_source/SimpleDesk-Admin.php';
    shd_load_language('sd_language/SimpleDeskAdmin');
    shd_load_plugin_files('hdadmin');
    shd_load_plugin_langfiles('hdadmin');
    // Now add the main SimpleDesk menu
    if (!empty($modSettings['helpdesk_active'])) {
        // The helpdesk action log
        if (empty($modSettings['shd_disable_action_log'])) {
            $admin_areas['maintenance']['areas']['logs']['subsections']['helpdesklog'] = array($txt['shd_admin_helpdesklog'], 'admin_forum', 'url' => $scripturl . '?action=admin;area=helpdesk_info;sa=actionlog');
        }
        // The main menu
        $admin_areas['helpdesk_info'] = array('title' => $txt['shd_helpdesk'], 'enabled' => allowedTo('admin_forum') || shd_allowed_to('admin_helpdesk', 0), 'areas' => array('helpdesk_info' => array('label' => $txt['shd_admin_info'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/simpledesk.png', 'function' => 'shd_admin_main', 'subsections' => array('main' => array($txt['shd_admin_info']), 'actionlog' => array($txt['shd_admin_actionlog'], 'enabled' => empty($modSettings['shd_disable_action_log'])), 'support' => array($txt['shd_admin_support']))), 'helpdesk_options' => array('label' => $txt['shd_admin_options'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/options.png', 'function' => 'shd_admin_main', 'subsections' => array('display' => array($txt['shd_admin_options_display']), 'posting' => array($txt['shd_admin_options_posting']), 'admin' => array($txt['shd_admin_options_admin']), 'standalone' => array($txt['shd_admin_options_standalone']), 'actionlog' => array($txt['shd_admin_options_actionlog']), 'notifications' => array($txt['shd_admin_options_notifications']))), 'helpdesk_cannedreplies' => array('label' => $txt['shd_admin_cannedreplies'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/cannedreplies.png', 'function' => 'shd_admin_main', 'subsections' => array()), 'helpdesk_customfield' => array('label' => $txt['shd_admin_custom_fields'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/custom_fields.png', 'function' => 'shd_admin_main', 'subsections' => array()), 'helpdesk_depts' => array('label' => $txt['shd_admin_departments'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/departments.png', 'function' => 'shd_admin_main', 'subsections' => array()), 'helpdesk_permissions' => array('label' => $txt['shd_admin_permissions'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/permissions.png', 'function' => 'shd_admin_main', 'subsections' => array()), 'helpdesk_plugins' => array('label' => $txt['shd_admin_plugins'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/plugins.png', 'function' => 'shd_admin_main', 'subsections' => array()), 'helpdesk_maint' => array('label' => $txt['shd_admin_maint'], 'file' => 'sd_source/SimpleDesk-Admin.php', 'icon' => 'shd/maintenance.png', 'function' => 'shd_admin_main', 'subsections' => array('main' => array($txt['shd_admin_maint']), 'search' => array($txt['shd_maint_search_settings'])))));
        // Now engage any hooks.
        call_integration_hook('shd_hook_adminmenu', array(&$admin_areas));
    }
}
Ejemplo n.º 12
0
function shd_notify_ticket_options()
{
    global $context, $txt, $smcFunc;
    $ticketinfo = shd_load_ticket();
    // This does permissions to access the ticket too.
    $ticket_starter = $ticketinfo['starter_id'] == $context['user']['id'];
    checkSession();
    if (empty($_REQUEST['notifyaction'])) {
        $_REQUEST['notifyaction'] = '';
    }
    // Get any existing entry.
    $query = $smcFunc['db_query']('', '
		SELECT notify_state
		FROM {db_prefix}helpdesk_notify_override
		WHERE id_member = {int:user}
			AND id_ticket = {int:ticket}', array('user' => $context['user']['id'], 'ticket' => $context['ticket_id']));
    if ($smcFunc['db_num_rows']($query) == 0) {
        $old_state = NOTIFY_PREFS;
    } else {
        list($old_state) = $smcFunc['db_fetch_row']($query);
    }
    $smcFunc['db_free_result']($query);
    switch ($_REQUEST['notifyaction']) {
        case 'monitor_on':
            if (!shd_allowed_to('shd_monitor_ticket_any', $ticketinfo['dept']) && (!$ticket_starter || !shd_allowed_to('shd_monitor_ticket_own', $ticketinfo['dept']))) {
                fatal_lang_error('cannot_monitor_ticket', false);
            }
            // Unlike turning it off, we might be turning it on from either just off, or ignored, so log that fact.
            if ($old_state == NOTIFY_ALWAYS) {
                break;
            } elseif ($old_state == NOTIFY_NEVER) {
                // Log turning off ignore list first
                shd_log_action('unignore', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            }
            // Then add the new status.
            $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_notify_override', array('id_member' => 'int', 'id_ticket' => 'int', 'notify_state' => 'int'), array($context['user']['id'], $context['ticket_id'], NOTIFY_ALWAYS), array('id_member', 'id_ticket'));
            shd_log_action('monitor', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            break;
        case 'monitor_off':
            if (!shd_allowed_to('shd_monitor_ticket_any', $ticketinfo['dept']) && (!$ticket_starter || !shd_allowed_to('shd_monitor_ticket_own', $ticketinfo['dept']))) {
                fatal_lang_error('cannot_unmonitor_ticket', false);
            }
            // Just delete the old status.
            $smcFunc['db_query']('', '
				DELETE FROM {db_prefix}helpdesk_notify_override
				WHERE id_member = {int:member}
					AND id_ticket = {int:ticket}', array('member' => $context['user']['id'], 'ticket' => $context['ticket_id']));
            shd_log_action('unmonitor', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            break;
        case 'ignore_on':
            if (!shd_allowed_to('shd_ignore_ticket_any', $ticketinfo['dept']) && (!$ticket_starter || !shd_allowed_to('shd_ignore_ticket_own', $ticketinfo['dept']))) {
                fatal_lang_error('cannot_monitor_ticket', false);
            }
            // Unlike turning it off, we might be turning it on from either just off, or ignored, so log that fact.
            if ($old_state == NOTIFY_NEVER) {
                break;
            } elseif ($old_state == NOTIFY_ALWAYS) {
                // Log turning off ignore list first
                shd_log_action('unmonitor', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            }
            $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_notify_override', array('id_member' => 'int', 'id_ticket' => 'int', 'notify_state' => 'int'), array($context['user']['id'], $context['ticket_id'], NOTIFY_NEVER), array('id_member', 'id_ticket'));
            shd_log_action('ignore', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            break;
        case 'ignore_off':
            if (!shd_allowed_to('shd_ignore_ticket_any', $ticketinfo['dept']) && (!$ticket_starter || !shd_allowed_to('shd_ignore_ticket_own', $ticketinfo['dept']))) {
                fatal_lang_error('cannot_unmonitor_ticket', false);
            }
            $smcFunc['db_query']('', '
				DELETE FROM {db_prefix}helpdesk_notify_override
				WHERE id_member = {int:member}
					AND id_ticket = {int:ticket}', array('member' => $context['user']['id'], 'ticket' => $context['ticket_id']));
            shd_log_action('unignore', array('ticket' => $context['ticket_id'], 'subject' => $ticketinfo['subject']));
            break;
        default:
            break;
    }
    redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
}
Ejemplo n.º 13
0
function shd_reply_restore()
{
    global $smcFunc, $user_info, $context, $sourcedir;
    checkSession('get');
    $_REQUEST['reply'] = empty($_REQUEST['reply']) ? 0 : (int) $_REQUEST['reply'];
    if (empty($_REQUEST['reply'])) {
        fatal_lang_error('shd_no_ticket', false);
    }
    // Check we can actually see the ticket we're restoring from, and that we can restore this reply
    $query_ticket = shd_db_query('', '
		SELECT hdt.id_ticket, hdt.id_dept, hdtr.id_member, hdt.id_member_started, hdt.id_member_updated, hdt.num_replies, hdt.subject, hdt.status, hdtr.message_status
		FROM {db_prefix}helpdesk_tickets AS hdt
			INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_ticket = hdtr.id_ticket)
		WHERE {query_see_ticket}
			AND hdtr.id_msg = {int:reply}
			AND hdt.id_first_msg != {int:reply2}', array('reply' => $_REQUEST['reply'], 'reply2' => $_REQUEST['reply']));
    if ($row = $smcFunc['db_fetch_assoc']($query_ticket)) {
        $smcFunc['db_free_result']($query_ticket);
        if ($row['status'] == TICKET_STATUS_DELETED || $row['status'] == TICKET_STATUS_CLOSED || $row['message_status'] != MSG_STATUS_DELETED || !shd_allowed_to('shd_restore_reply_any', $row['id_dept']) && (!shd_allowed_to('shd_restore_reply_own', $row['id_dept']) || $user_info['id'] != $row['id_member'])) {
            fatal_lang_error('shd_cannot_restore_reply', false);
        }
        $context['ticket_id'] = (int) $row['id_ticket'];
        $subject = $row['subject'];
        $starter = $row['id_member_started'];
        $replier = $row['id_member_updated'];
        $num_replies = $row['num_replies'];
    } else {
        $smcFunc['db_free_result']($query_ticket);
        fatal_lang_error('shd_no_ticket', false);
    }
    // The ticket's id is in $context['ticket_id'], the reply id in $_REQUEST['reply'].
    call_integration_hook('shd_hook_restorereply');
    // OK, let's clear this one, hasta la vista... ticket.
    shd_db_query('', '
		UPDATE {db_prefix}helpdesk_ticket_replies
		SET message_status = {int:msg_status_deleted}
		WHERE id_msg = {int:reply}', array('msg_status_deleted' => MSG_STATUS_NORMAL, 'reply' => $_REQUEST['reply']));
    // Captain's Log, stardate 18.3.10.1010
    shd_log_action('restore_reply', array('ticket' => $context['ticket_id'], 'subject' => $subject, 'msg' => $_REQUEST['reply']));
    // Fix the topic data
    list($starter, $replier, $num_replies) = shd_recalc_ids($context['ticket_id']);
    $query_reply = shd_db_query('', '
		UPDATE {db_prefix}helpdesk_tickets
		SET status = {int:status}
		WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'], 'status' => shd_determine_status('restorereply', $starter, $replier, $num_replies, $row['id_dept'])));
    // Expire the cache of count(active tickets)
    shd_clear_active_tickets($row['id_dept']);
    redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
}
Ejemplo n.º 14
0
function shd_admin_maint_massdeptmove()
{
    global $context, $txt, $smcFunc, $sourcedir;
    checkSession('request');
    $context['page_title'] = $txt['shd_admin_maint_massdeptmove'];
    $depts = shd_allowed_to('access_helpdesk', false);
    $_POST['id_dept_from'] = isset($_POST['id_dept_from']) ? (int) $_POST['id_dept_from'] : 0;
    $_POST['id_dept_to'] = isset($_POST['id_dept_to']) ? (int) $_POST['id_dept_to'] : 0;
    if ($_POST['id_dept_from'] == 0 || $_POST['id_dept_to'] == 0 || !in_array($_POST['id_dept_from'], $depts) || !in_array($_POST['id_dept_to'], $depts)) {
        fatal_lang_error('shd_unknown_dept', false);
    } elseif ($_POST['id_dept_from'] == $_POST['id_dept_to']) {
        fatal_lang_error('shd_admin_maint_massdeptmove_samedept', false);
    }
    $clauses = array();
    if (empty($_POST['moveopen'])) {
        $clauses[] = 'AND status NOT IN (' . implode(',', array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_USER, TICKET_STATUS_PENDING_STAFF, TICKET_STATUS_WITH_SUPERVISOR, TICKET_STATUS_ESCALATED)) . ')';
    }
    if (empty($_POST['moveclosed'])) {
        $clauses[] = 'AND status != ' . TICKET_STATUS_CLOSED;
    }
    if (empty($_POST['movedeleted'])) {
        $clauses[] = 'AND status != ' . TICKET_STATUS_DELETED;
    }
    $_POST['movelast_less_days'] = isset($_POST['movelast_less_days']) && !empty($_POST['movelast_less']) ? (int) $_POST['movelast_less_days'] : 0;
    if ($_POST['movelast_less_days'] > 0) {
        $clauses[] = 'AND last_updated >= ' . (time() - $_POST['movelast_less_days'] * 86400);
    }
    $_POST['movelast_more_days'] = isset($_POST['movelast_more_days']) && !empty($_POST['movelast_more']) ? (int) $_POST['movelast_more_days'] : 0;
    if ($_POST['movelast_more_days'] > 0) {
        $clauses[] = 'AND last_updated < ' . (time() - $_POST['movelast_more_days'] * 86400);
    }
    // OK, let's start. How many tickets are there to move?
    if (empty($_POST['massdeptmove'])) {
        $query = $smcFunc['db_query']('', '
			SELECT COUNT(*)
			FROM {db_prefix}helpdesk_tickets
			WHERE id_dept = {int:dept_from} ' . implode(' ', $clauses), array('dept_from' => $_POST['id_dept_from']));
        list($count) = $smcFunc['db_fetch_row']($query);
        $smcFunc['db_free_result']($query);
        if (!empty($count)) {
            $_POST['massdeptmove'] = $count;
        } else {
            $_GET['done'] = true;
        }
    }
    // OK, so we know we're going to be doing some tickets, or do we?
    $_POST['tickets_done'] = isset($_POST['tickets_done']) ? (int) $_POST['tickets_done'] : 0;
    if (isset($_GET['done']) || $_POST['tickets_done'] >= $_POST['massdeptmove']) {
        $context['sub_template'] = 'shd_admin_maint_massdeptmovedone';
        return;
    }
    // So, do this batch.
    $step_count = 10;
    $tickets = array();
    // We don't need to get particularly clever; whatever tickets we did in any previous batch, well, they will be gone by now.
    $query = $smcFunc['db_query']('', '
		SELECT id_ticket, subject
		FROM {db_prefix}helpdesk_tickets
		WHERE id_dept = {int:dept_from} ' . implode(' ', $clauses) . '
		ORDER BY id_ticket
		LIMIT {int:step}', array('dept_from' => $_POST['id_dept_from'], 'step' => $step_count));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        $tickets[$row['id_ticket']] = $row['subject'];
    }
    $smcFunc['db_free_result']($query);
    if (!empty($tickets)) {
        // Get department ids.
        $query = $smcFunc['db_query']('', '
			SELECT id_dept, dept_name
			FROM {db_prefix}helpdesk_depts
			WHERE id_dept IN ({array_int:depts})', array('depts' => array($_POST['id_dept_from'], $_POST['id_dept_to'])));
        $depts = array();
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $depts[$row['id_dept']] = $row['dept_name'];
        }
        $smcFunc['db_free_result']($query);
        // OK, we have the ticket ids. Now we'll move the set and log each one moved.
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}helpdesk_tickets
			SET id_dept = {int:dept_to}
			WHERE id_ticket IN ({array_int:ids})', array('dept_to' => $_POST['id_dept_to'], 'ids' => array_keys($tickets)));
        // This is the same every time.
        $log_params = array('old_dept_id' => $_POST['id_dept_from'], 'old_dept_name' => $depts[$_POST['id_dept_from']], 'new_dept_id' => $_POST['id_dept_to'], 'new_dept_name' => $depts[$_POST['id_dept_to']]);
        foreach ($tickets as $id => $subject) {
            $log_params['subject'] = $subject;
            $log_params['ticket'] = $id;
            shd_log_action('move_dept', $log_params);
        }
        shd_clear_active_tickets($_POST['id_dept_from']);
        shd_clear_active_tickets($_POST['id_dept_to']);
        $_POST['tickets_done'] += $step_count;
    }
    // Prepare to shove everything we need into the form so we can go again.
    $context['continue_countdown'] = 3;
    $context['continue_get_data'] = '?action=admin;area=helpdesk_maint;sa=massdeptmove;' . $context['session_var'] . '=' . $context['session_id'];
    $context['continue_post_data'] = '
		<input type="hidden" name="id_dept_from" value="' . $_POST['id_dept_from'] . '" />
		<input type="hidden" name="id_dept_to" value="' . $_POST['id_dept_to'] . '" />
		<input type="hidden" name="tickets_done" value="' . $_POST['tickets_done'] . '" />
		<input type="hidden" name="massdeptmove" value="' . $_POST['massdeptmove'] . '" />';
    if (!empty($_POST['moveopen'])) {
        $context['continue_post_data'] .= '
		<input type="hidden" name="moveopen" value="' . $_POST['moveopen'] . '" />';
    }
    if (!empty($_POST['moveclosed'])) {
        $context['continue_post_data'] .= '
		<input type="hidden" name="moveclosed" value="' . $_POST['moveclosed'] . '" />';
    }
    if (!empty($_POST['movedeleted'])) {
        $context['continue_post_data'] .= '
		<input type="hidden" name="movedeleted" value="' . $_POST['movedeleted'] . '" />';
    }
    if ($_POST['movelast_less_days'] > 0) {
        $context['continue_post_data'] .= '
		<input type="hidden" name="movelast_less" value="1" />
		<input type="hidden" name="movelast_less_days" value="' . $_POST['movelast_less_days'] . '" />';
    }
    if ($_POST['movelast_more_days'] > 0) {
        $context['continue_post_data'] .= '
		<input type="hidden" name="movelast_more" value="1" />
		<input type="hidden" name="movelast_more_days" value="' . $_POST['movelast_more_days'] . '" />';
    }
    $context['sub_template'] = 'not_done';
    $context['continue_percent'] = $_POST['tickets_done'] > $_POST['massdeptmove'] ? 100 : floor($_POST['tickets_done'] / $_POST['massdeptmove'] * 100);
}
Ejemplo n.º 15
0
/**
 *	Add the SimpleDesk options to the main site menu.
 *
 *	@param array &$menu_buttons The main menu buttons as provided by Subs.php.
 *	@since 2.0
*/
function shd_main_menu(&$menu_buttons)
{
    global $context, $txt, $scripturl, $modSettings;
    if (!empty($modSettings['helpdesk_active'])) {
        // Stuff we'll always do in SD if active
        $helpdesk_admin = $context['user']['is_admin'] || shd_allowed_to('admin_helpdesk', 0);
        // 1. Add the main menu if we can.
        if (shd_allowed_to(array('access_helpdesk', 'admin_helpdesk'), 0) && empty($modSettings['shd_hidemenuitem'])) {
            // Because some items may have been removed at this point, let's try a list of possible places after which we can add the button.
            $order = array('search', 'profile', 'forum', 'pm', 'help', 'home');
            $pos = null;
            foreach ($order as $item) {
                if (isset($menu_buttons[$item])) {
                    $pos = $item;
                    break;
                }
            }
            if ($pos === null) {
                $menu_buttons['helpdesk'] = array();
            } else {
                // OK, we're adding it after something.
                $temp = $menu_buttons;
                $menu_buttons = array();
                foreach ($temp as $k => $v) {
                    $menu_buttons[$k] = $v;
                    if ($k == $pos) {
                        $menu_buttons['helpdesk'] = array();
                    }
                }
            }
            $menu_buttons['helpdesk'] += array('title' => $modSettings['helpdesk_active'] && SMF != 'SSI' ? shd_get_active_tickets() : $txt['shd_helpdesk'], 'href' => $scripturl . '?action=helpdesk;sa=main', 'show' => true, 'active_button' => false, 'sub_buttons' => array('newticket' => array('title' => $txt['shd_new_ticket'], 'href' => $scripturl . '?action=helpdesk;sa=newticket', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket', 0)), 'newproxyticket' => array('title' => $txt['shd_new_ticket_proxy'], 'href' => $scripturl . '?action=helpdesk;sa=newticket;proxy', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket', 0) && shd_allowed_to('shd_post_proxy', 0)), 'closedtickets' => array('title' => $txt['shd_tickets_closed'], 'href' => $scripturl . '?action=helpdesk;sa=closedtickets', 'show' => SMF == 'SSI' ? false : shd_allowed_to(array('shd_view_closed_own', 'shd_view_closed_any'), 0)), 'recyclebin' => array('title' => $txt['shd_recycle_bin'], 'href' => $scripturl . '?action=helpdesk;sa=recyclebin', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_access_recyclebin', 0))));
            if ($helpdesk_admin) {
                $menu_buttons['helpdesk']['sub_buttons']['admin'] = array('title' => $txt['admin'], 'href' => $scripturl . '?action=admin;area=helpdesk_info', 'show' => SMF == 'SSI' ? false : empty($modSettings['shd_hidemenuitem']) && $helpdesk_admin, 'sub_buttons' => shd_main_menu_admin($helpdesk_admin));
            }
            $item = false;
            foreach ($menu_buttons['helpdesk']['sub_buttons'] as $key => $value) {
                if (!empty($value['show'])) {
                    $item = $key;
                } else {
                    unset($menu_buttons['helpdesk']['sub_buttons'][$key]);
                }
            }
            if (!empty($item)) {
                $menu_buttons['helpdesk']['sub_buttons'][$item]['is_last'] = true;
            }
        }
        // Add the helpdesk admin option to the admin menu, if board integration is disabled.
        if (!empty($modSettings['shd_hidemenuitem']) && $helpdesk_admin) {
            // It's possible the admin button got eaten already, so we may have to recreate it.
            if (empty($menu_buttons['admin'])) {
                $admin_menu = array('title' => $txt['admin'], 'href' => $scripturl . '?action=admin', 'show' => true, 'active_button' => false, 'sub_buttons' => array());
                // Trouble is, now we've done that, it's in the wrong damn place. So step through and insert our menu into just after the SD menu
                $old_menu_buttons = $menu_buttons;
                $menu_buttons = array();
                $added = false;
                foreach ($old_menu_buttons as $area => $detail) {
                    if (!$added && ($area == 'moderate' || $area == 'profile')) {
                        $menu_buttons['admin'] = $admin_menu;
                        $added = true;
                    }
                    $menu_buttons[$area] = $detail;
                }
            }
            // Make sure the button is visible if you can admin forum
            $menu_buttons['admin']['show'] = true;
            // Remove the is_last item
            foreach ($menu_buttons['admin']['sub_buttons'] as $key => $value) {
                if (!empty($value['is_last'])) {
                    unset($menu_buttons['admin']['sub_buttons'][$key]['is_last']);
                }
            }
            // Add the new button
            $menu_buttons['admin']['sub_buttons']['helpdesk_admin'] = array('title' => $txt['shd_helpdesk'], 'href' => $scripturl . '?action=admin;area=helpdesk_info', 'show' => true, 'is_last' => true, 'sub_buttons' => shd_main_menu_admin($helpdesk_admin));
        }
        if (shd_allowed_to(array('shd_view_profile_own', 'shd_view_profile_any'), 0)) {
            // Hmm, this could be tricky. It's possible the main menu has been eaten by permissions at this point, so just in case, reconstruct what's missing.
            if (empty($menu_buttons['profile'])) {
                $profile_menu = array('title' => $txt['profile'], 'href' => $scripturl . '?action=profile', 'active_button' => false, 'sub_buttons' => array());
                // Trouble is, now we've done that, it's in the wrong damn place. So step through and insert our menu into just after the SD menu
                $old_menu_buttons = $menu_buttons;
                $menu_buttons = array();
                $added = false;
                foreach ($old_menu_buttons as $area => $detail) {
                    $menu_buttons[$area] = $detail;
                    if ($area == 'helpdesk') {
                        $menu_buttons['profile'] = $profile_menu;
                        $added = true;
                    }
                }
                if (!$added) {
                    $menu_buttons['profile'] = $profile_menu;
                }
            }
            // Remove the is_last item
            foreach ($menu_buttons['profile']['sub_buttons'] as $key => $value) {
                if (!empty($value['is_last'])) {
                    unset($menu_buttons['profile']['sub_buttons'][$key]['is_last']);
                }
            }
            // If we're in HD only mode, we definitely don't want the regular forum profile item.
            if (!empty($modSettings['shd_helpdesk_only'])) {
                unset($menu_buttons['profile']['sub_buttons']['profile'], $menu_buttons['profile']['sub_buttons']['summary']);
            }
            // Add the helpdesk profile to the profile menu (either the original or our reconstituted one)
            $menu_buttons['profile']['show'] = true;
            $menu_buttons['profile']['sub_buttons']['hd_profile'] = array('title' => $txt['shd_helpdesk_profile'], 'href' => $scripturl . '?action=profile;area=helpdesk', 'show' => true, 'is_last' => true);
        }
        // Stuff we'll only do if in standalone mode
        if (!empty($modSettings['shd_helpdesk_only'])) {
            $menu_buttons['home'] = array('title' => $modSettings['helpdesk_active'] && SMF != 'SSI' ? shd_get_active_tickets() : $txt['shd_helpdesk'], 'href' => $scripturl . '?action=helpdesk;sa=main', 'show' => $modSettings['helpdesk_active'], 'sub_buttons' => array('newticket' => array('title' => $txt['shd_new_ticket'], 'href' => $scripturl . '?action=helpdesk;sa=newticket', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket', 0)), 'newproxyticket' => array('title' => $txt['shd_new_ticket_proxy'], 'href' => $scripturl . '?action=helpdesk;sa=newticket;proxy', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_new_ticket', 0) && shd_allowed_to('shd_post_proxy', 0)), 'closedtickets' => array('title' => $txt['shd_tickets_closed'], 'href' => $scripturl . '?action=helpdesk;sa=closedtickets', 'show' => SMF == 'SSI' ? false : shd_allowed_to(array('shd_view_closed_own', 'shd_view_closed_any'), 0)), 'recyclebin' => array('title' => $txt['shd_recycle_bin'], 'href' => $scripturl . '?action=helpdesk;sa=recyclebin', 'show' => SMF == 'SSI' ? false : shd_allowed_to('shd_access_recyclebin', 0))), 'active_button' => false);
            if ($helpdesk_admin) {
                $menu_buttons['home']['sub_buttons']['admin'] = array('title' => $txt['admin'], 'href' => $scripturl . '?action=admin;area=helpdesk_info', 'show' => SMF == 'SSI' ? false : empty($modSettings['shd_hidemenuitem']) && $helpdesk_admin, 'is_last' => true, 'sub_buttons' => shd_main_menu_admin($helpdesk_admin));
            }
            $item = false;
            foreach ($menu_buttons['home']['sub_buttons'] as $key => $value) {
                if (!empty($value['show'])) {
                    $item = $key;
                } else {
                    unset($menu_buttons['home']['sub_buttons'][$key]);
                }
            }
            if (!empty($item)) {
                $menu_buttons['home']['sub_buttons'][$item]['is_last'] = true;
            }
            unset($menu_buttons['helpdesk']);
            // Disable help, search, calendar, moderation center
            unset($menu_buttons['help'], $menu_buttons['search'], $menu_buttons['calendar'], $menu_buttons['moderate']);
            $context['allow_search'] = false;
            $context['allow_calendar'] = false;
            $context['allow_moderation_center'] = false;
            // Disable PMs
            if (!empty($modSettings['shd_disable_pm'])) {
                $context['allow_pm'] = false;
                $menu_buttons['pm']['show'] = false;
                $context['user']['unread_messages'] = 0;
                // to disable it trying to add to the menu item
            }
            // Disable memberlist
            if (!empty($modSettings['shd_disable_mlist'])) {
                $context['allow_memberlist'] = false;
                $menu_buttons['mlist']['show'] = false;
            }
        }
        // Now engage any hooks.
        call_integration_hook('shd_hook_mainmenu', array(&$menu_buttons));
    }
}
/**
 *	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);
    }
}
Ejemplo n.º 17
0
/**
 *	Handles the actual assignment form, validates it and carries it out.
 *
 *	Primarily this is just about receiving the form, making the same checks that {@link shd_assign()} does and then
 *	logging the action before passing over to {@link shd_commit_assignment()} to actually assign the ticket.
 *
 *	@see shd_assign()
 *	@see shd_commit_assignment()
 *	@since 1.0
*/
function shd_assign2()
{
    global $context, $smcFunc, $user_info, $sourcedir;
    checkSession();
    checkSubmitOnce('check');
    if (empty($context['ticket_id'])) {
        fatal_lang_error('shd_no_ticket');
    }
    $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket';
    $assignee = isset($_REQUEST['to_user']) ? (int) $_REQUEST['to_user'] : 0;
    // Get ticket details - and kick it out if they shouldn't be able to see it.
    $query = shd_db_query('', '
		SELECT id_member_started, id_member_assigned, private, subject, status, id_dept
		FROM {db_prefix}helpdesk_tickets AS hdt
		WHERE {query_see_ticket} AND id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
    $log_params = array();
    if ($row = $smcFunc['db_fetch_row']($query)) {
        list($ticket_starter, $ticket_owner, $private, $subject, $status, $dept) = $row;
        // The core details that we'll be logging
        $log_params = array('subject' => $subject, 'ticket' => $context['ticket_id']);
    } else {
        $smcFunc['db_free_result']($query);
        fatal_lang_error('shd_no_ticket');
    }
    // Just in case, are they cancelling?
    if (isset($_REQUEST['cancel'])) {
        redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
    }
    if ($status == TICKET_STATUS_CLOSED || $status == TICKET_STATUS_DELETED) {
        fatal_lang_error('shd_cannot_assign', false);
    }
    if (shd_allowed_to('shd_assign_ticket_any', $dept)) {
        if ($assignee == 0) {
            shd_log_action('unassign', $log_params);
            shd_commit_assignment($context['ticket_id'], 0);
        } else {
            $members = shd_get_possible_assignees($private, $ticket_starter, $dept);
            if (in_array($assignee, $members)) {
                global $user_profile;
                loadMemberData($assignee, false, 'minimal');
                $log_params += array('user_id' => $assignee, 'user_name' => $user_profile[$assignee]['real_name']);
                shd_log_action('assign', $log_params);
                shd_commit_assignment($context['ticket_id'], $assignee);
            } else {
                fatal_lang_error('shd_assigned_not_permitted', false);
            }
        }
    } elseif (shd_allowed_to('shd_assign_ticket_own', $dept) && shd_allowed_to('shd_staff', $dept)) {
        if ($ticket_owner == 0) {
            $log_params += array('user_id' => $user_info['id'], 'user_name' => $user_info['name']);
            shd_log_action('assign', $log_params);
            shd_commit_assignment($context['ticket_id'], $user_info['id']);
        } elseif ($ticket_starter == $user_info['id']) {
            shd_log_action('unassign', $log_params);
            shd_commit_assignment($context['ticket_id'], 0);
        } else {
            // oops, assigned to somebody else
            fatal_lang_error('shd_cannot_assign_other', false);
        }
    } else {
        fatal_lang_error('shd_cannot_assign', false);
    }
}
Ejemplo n.º 18
0
/**
 *	Handles moving a topic into the helpdesk.
 *
 *	After checking permissions, and so on, begin to actually move posts.
 *
 *	Broadly this is done using {@link shd_create_ticket_post()}, which has hooks specifically to deal with post modification times (written in specifically to ease this function's workload)
 *
 *	Operations:
 *	- get the topic information (and checking topic access permission in the process)
 *	- identify the status of the topic (new/with staff/with user)
 *	- create the new ticket from these details
 *	- assuming there are replies, query for them
 *	- step through and repost
 *	- send the notification PM if we're doing that
 *	- update the attachments table
 *	- update the action log
 *	- remove the topic from the forum
 *
 *	@see shd_topictoticket()
 *	@since 1.0
*/
function shd_topictoticket2()
{
    global $smcFunc, $context, $txt, $modSettings, $scripturl, $sourcedir;
    checkSession();
    checkSubmitOnce('check');
    $_REQUEST['dept'] = isset($_REQUEST['dept']) ? (int) $_REQUEST['dept'] : 0;
    if (empty($_REQUEST['dept'])) {
        $_REQUEST['dept'] = -1;
    }
    // which is never a valid department!
    if (!shd_allowed_to('shd_topic_to_ticket', $_REQUEST['dept']) || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) {
        fatal_lang_error('shd_cannot_move_topic', false);
    }
    if (empty($_REQUEST['topic'])) {
        fatal_lang_error('shd_no_topic');
    }
    $context['topic_id'] = (int) $_REQUEST['topic'];
    // Just in case, are they cancelling?
    if (isset($_REQUEST['cancel'])) {
        redirectexit('topic=' . $context['topic_id']);
    }
    if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) {
        fatal_lang_error('shd_move_no_pm_topic', false);
    }
    require_once $sourcedir . '/sd_source/Subs-SimpleDeskPost.php';
    // Fetch the topic information.
    $request = shd_db_query('', '
		SELECT m.subject, t.id_board, t.id_member_started, m.body, t.id_first_msg, m.smileys_enabled, t.id_member_updated, t.num_replies,
		m.poster_email, m.poster_name, m.poster_ip, m.poster_time, m.modified_time, m.modified_name, m.id_msg
		FROM {db_prefix}topics AS t
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
			INNER JOIN {db_prefix}boards AS b ON (t.id_board = b.id_board)
		WHERE {query_see_board} AND t.id_topic = {int:topic}
		LIMIT 1', array('topic' => $context['topic_id']));
    if ($smcFunc['db_num_rows']($request) == 0) {
        fatal_lang_error('shd_move_ticket_not_created');
    } else {
        list($subject, $board, $owner, $body, $firstmsg, $smileys_enabled, $memberupdated, $numreplies, $postername, $posteremail, $posterip, $postertime, $modified_time, $modified_name, $smf_id_msg) = $smcFunc['db_fetch_row']($request);
    }
    $smcFunc['db_free_result']($request);
    // Figure out what the status of the ticket should be.
    $status = shd_determine_status('topictoticket', $owner, $memberupdated, $numreplies, $_REQUEST['dept']);
    // Are we changing the subject?
    $old_subject = $subject;
    $subject = !empty($_POST['change_subject']) && !empty($_POST['subject']) ? $_POST['subject'] : $subject;
    // Just before we do this, make sure we call any hooks. $context and $_POST have lots of interesting things for us.
    call_integration_hook('shd_hook_topictoticket');
    // All okay, it seems. Let's go create the ticket.
    $msg_assoc = array();
    $msgOptions = array('body' => $body, 'smileys_enabled' => !empty($smileys_enabled) ? 1 : 0, 'modified' => array('time' => $modified_time, 'name' => $modified_name), 'time' => $postertime);
    $ticketOptions = array('dept' => $_REQUEST['dept'], 'subject' => $subject, 'mark_as_read' => false, 'private' => false, 'status' => $status, 'urgency' => 0, 'assigned' => 0);
    $posterOptions = array('id' => $owner, 'name' => $postername, 'email' => $posteremail, 'ip' => $posterip);
    shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions);
    $msg_assoc[$smf_id_msg] = $msgOptions['id'];
    // Ticket created, let's dig out the replies and post them in the ticket, if there are any.
    if (isset($ticketOptions['id'])) {
        $request = shd_db_query('', '
			SELECT body, id_member, poster_time, poster_name, poster_email, poster_ip, smileys_enabled, id_msg
			FROM {db_prefix}messages
			WHERE id_topic = {int:topic}
			AND id_msg != {int:topic_msg}', array('topic' => $context['topic_id'], 'topic_msg' => $firstmsg));
        $num_replies = $smcFunc['db_num_rows']($request) + 1;
        // Plus one since we want to count the main ticket post as well.
        // The ID of the ticket we created
        $ticket = $ticketOptions['id'];
        if ($smcFunc['db_num_rows']($request) != 0) {
            // Now loop through each reply and post it.  Hopefully there aren't too many. *looks at clock*
            while ($row = $smcFunc['db_fetch_assoc']($request)) {
                $msgOptions = array('body' => $row['body'], 'smileys_enabled' => !empty($row['smileys_enabled']) ? 1 : 0);
                $ticketOptions = array('id' => $ticket, 'mark_as_read' => false);
                $posterOptions = array('id' => $row['id_member'], 'name' => !empty($row['poster_name']) ? $row['poster_name'] : '', 'email' => !empty($row['poster_email']) ? $row['poster_email'] : '', 'ip' => !empty($row['poster_ip']) ? $row['poster_ip'] : '');
                shd_create_ticket_post($msgOptions, $ticketOptions, $posterOptions);
                $msg_assoc[$row['id_msg']] = $msgOptions['id'];
            }
        }
        // Ticket: check; Replies: check; Notfiy the topic starter, if desired.
        if (isset($_POST['send_pm'])) {
            require_once $sourcedir . '/Subs-Post.php';
            $request = shd_db_query('pm_find_username', '
				SELECT id_member, real_name
				FROM {db_prefix}members
				WHERE id_member = {int:user}
				LIMIT 1', array('user' => $owner));
            list($userid, $username) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
            // Fix the content
            $replacements = array('{user}' => $username, '{subject}' => $old_subject, '{link}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $ticket);
            $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']);
            $recipients = array('to' => array($owner), 'bcc' => array());
            sendpm($recipients, $txt['shd_ticket_moved_subject_topic'], un_htmlspecialchars($message));
        }
        // And now for something completely different: attachments
        if (!empty($msg_assoc)) {
            // 1. Get all the attachments for these messages from the attachments table
            $attachIDs = array();
            $query = shd_db_query('', '
				SELECT id_attach, id_msg
				FROM {db_prefix}attachments
				WHERE id_msg IN ({array_int:smf_msgs})', array('smf_msgs' => array_keys($msg_assoc)));
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $attachIDs[] = $row;
            }
            $smcFunc['db_free_result']($query);
            if (!empty($attachIDs)) {
                // 2. Do the switch
                // 2.1. Add them to SD's tables
                $array = array();
                foreach ($attachIDs as $attach) {
                    $array[] = array($attach['id_attach'], $ticket, $msg_assoc[$attach['id_msg']]);
                }
                $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int'), $array, array('id_attach'));
                // 2.2. "Remove" them from SMF's table
                shd_db_query('', '
					UPDATE {db_prefix}attachments
					SET id_msg = 0
					WHERE id_msg IN ({array_int:smf_msgs})', array('smf_msgs' => array_keys($msg_assoc)));
            }
        }
        // Now we'll add this to the log.
        $log_params = array('subject' => $subject, 'ticket' => $ticket);
        shd_log_action('topictoticket', $log_params);
        // Update post counts.
        $request = shd_db_query('', '
			SELECT id_member
			FROM {db_prefix}messages
			WHERE id_topic = {int:topic}', array('topic' => $context['topic_id']));
        $posters = array();
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            if (!isset($posters[$row['id_member']])) {
                $posters[$row['id_member']] = 0;
            }
            $posters[$row['id_member']]++;
        }
        $smcFunc['db_free_result']($request);
        foreach ($posters as $id_member => $posts) {
            updateMemberData($id_member, array('posts' => 'posts - ' . $posts));
        }
        // Lastly, delete the topic from the database.
        shd_db_query('', '
			DELETE FROM {db_prefix}topics
			WHERE id_topic = {int:topic}
			LIMIT 1', array('topic' => $context['topic_id']));
        // And the replies, too.
        shd_db_query('', '
			DELETE FROM {db_prefix}messages
			WHERE id_topic = {int:topic}', array('topic' => $context['topic_id']));
        // Update the stats.
        require_once $sourcedir . '/Subs-Post.php';
        updateStats('message');
        updateStats('topic');
        updateLastMessages($board);
        // Update board post counts.
        shd_db_query('', '
			UPDATE {db_prefix}boards
			SET num_topics = num_topics - 1,
				num_posts = num_posts - {int:num_posts}
			WHERE id_board = {int:board}', array('board' => $board, 'num_posts' => $num_replies));
    } else {
        fatal_lang_error('shd_move_ticket_not_created', false);
    }
    // Send them to the ticket.
    redirectexit('action=helpdesk;sa=ticket;ticket=' . $ticket);
}
/**
 *	Enforces a user having a given permission and returning to a fatal error message if not.
 *
 *	All fatal-level SimpleDesk-specific permissions should be checked with this function. Any other permission check that is
 *	not specifically SimpleDesk-related should use isAllowedTo instead. Note that this is a void function because should this
 *	fail, SMF execution will be halted.
 *
 *	Prior to 1.0, this function was in Subs-SimpleDesk.php
 *
 *	@param mixed $permission A string or array of strings naming a permission or permissions that wish to be examined.
 *	@param int $dept A number indicating a department that the user must the permission in, or 0 for not caring which department provided the user has that permission in at least one department.
 *	@see shd_allowed_to()
 *	@since 1.0
*/
function shd_is_allowed_to($permission, $dept = 0)
{
    global $user_info, $txt;
    $permission = is_array($permission) ? $permission : (array) $permission;
    if (!shd_allowed_to($permission, $dept)) {
        // Pick the last array entry as the permission shown as the error.
        $error_permission = array_shift($permission);
        // If they are a guest, show a login. (because the error might be gone if they do!)
        if ($user_info['is_guest']) {
            loadLanguage('Errors');
            is_not_guest($txt['cannot_' . $error_permission]);
        }
        // Clear the action because they aren't really doing that!
        $_GET['action'] = '';
        $_GET['board'] = '';
        $_GET['topic'] = '';
        writeLog(true);
        fatal_lang_error('cannot_' . $error_permission, false);
        // Getting this far is a really big problem, but let's try our best to prevent any cases...
        trigger_error('Hacking attempt...', E_USER_ERROR);
    }
}
Ejemplo n.º 20
0
function shd_search2()
{
    global $context, $smcFunc, $txt, $modSettings, $scripturl, $sourcedir;
    shd_is_allowed_to('shd_search', 0);
    if (!empty($context['load_average']) && !empty($modSettings['loadavg_search']) && $context['load_average'] >= $modSettings['loadavg_search']) {
        fatal_lang_error('loadavg_search_disabled', false);
    }
    // No, no, no... this is a bit hard on the server, so don't you go prefetching it!
    if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') {
        ob_end_clean();
        header('HTTP/1.1 403 Forbidden');
        die;
    }
    // We will need this.
    require_once $sourcedir . '/sd_source/Subs-SimpleDeskSearch.php';
    loadTemplate('sd_template/SimpleDesk-Search');
    $context['page_title'] = $txt['shd_search_results'];
    $context['linktree'][] = array('name' => $txt['shd_search_results']);
    $context['search_clauses'] = array('{query_see_ticket}');
    $context['search_params'] = array();
    // Departments first.
    $visible_depts = shd_allowed_to('access_helpdesk', false);
    $using_depts = array();
    if (!empty($_POST['search_dept']) && is_array($_POST['search_dept'])) {
        foreach ($_POST['search_dept'] as $dept) {
            if ((int) $dept > 0) {
                $using_depts[] = (int) $dept;
            }
        }
    }
    if (!empty($using_depts)) {
        $using_depts = array_intersect($using_depts, $visible_depts);
    }
    // No departments? Can't really do a lot, sorry. Bye then.
    if (empty($using_depts)) {
        return $context['sub_template'] = 'search_no_results';
    }
    // Is the selected list the same size as the list we can see? If it is, theory says that means we're picking every department we can see and don't need to exclude it.
    if (count($using_depts) != count($visible_depts)) {
        $context['search_clauses'][] = 'hdt.id_dept IN ({array_int:visible_depts})';
        $context['search_params']['visible_depts'] = $using_depts;
        // Also, we need to get the department list for displaying, only if we can actually see multiple departments at all.
        if ($context['shd_multi_dept']) {
            $query = $smcFunc['db_query']('', '
				SELECT id_dept, dept_name
				FROM {db_prefix}helpdesk_depts
				WHERE id_dept IN ({array_int:dept_list})
				ORDER BY dept_order', array('dept_list' => $using_depts));
            $context['search_dept_list'] = array();
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $context['search_dept_list'][$row['id_dept']] = $row['dept_name'];
            }
            $smcFunc['db_free_result']($query);
        }
    }
    // Ticket urgency
    $using_urgency = array();
    if (!empty($_POST['urgency']) && is_array($_POST['urgency'])) {
        foreach ($_POST['urgency'] as $urgency) {
            $urgency = (int) $urgency;
            if ($urgency >= 0 && $urgency <= 5) {
                // All the currently defined urgencies
                $using_urgency[] = $urgency;
            }
        }
    }
    if (empty($using_urgency)) {
        return $context['sub_template'] = 'search_no_results';
    } else {
        $using_urgency = array_unique($using_urgency);
        if (count($using_urgency) < 6) {
            // We have less than 6 selected urgencies, which means we actually need to filter on them, as opposed to if all 6 are selected when we don't.
            $context['search_clauses'][] = 'hdt.urgency IN ({array_int:urgency})';
            $context['search_params']['urgency'] = $using_urgency;
        }
    }
    // Ticket scope
    // All empty? If so, bye.
    if (empty($_POST['scope_open']) && empty($_POST['scope_closed']) && empty($_POST['scope_recycle'])) {
        return $context['sub_template'] = 'search_no_results';
    } elseif (empty($_POST['scope_open']) || empty($_POST['scope_closed']) || empty($_POST['scope_recycle'])) {
        $status = array();
        if (!empty($_POST['scope_open'])) {
            $status = array_merge($status, array(TICKET_STATUS_NEW, TICKET_STATUS_PENDING_STAFF, TICKET_STATUS_PENDING_USER, TICKET_STATUS_WITH_SUPERVISOR, TICKET_STATUS_ESCALATED));
        }
        if (!empty($_POST['scope_closed'])) {
            $status = array_merge($status, array(TICKET_STATUS_CLOSED));
        }
        if (!empty($_POST['scope_recycle'])) {
            $status = array_merge($status, array(TICKET_STATUS_DELETED));
        }
        $context['search_clauses'][] = 'hdt.status IN ({array_int:status})';
        $context['search_params']['status'] = $status;
        // That's ticket level status taken care of. We'll pick up recycled items in non recycled tickets separately since it's only relevant if you're actually searching text.
    }
    // Ticket starter
    $starters = shd_get_named_people('starter');
    if (!empty($starters)) {
        $context['search_clauses'][] = 'hdt.id_member_started IN ({array_int:member_started})';
        $context['search_params']['member_started'] = $starters;
    }
    // Ticket assigned to
    $assignees = shd_get_named_people('assignee');
    if (!empty($assignees)) {
        $context['search_clauses'][] = 'hdt.id_member_assigned IN ({array_int:member_assigned})';
        $context['search_params']['member_assigned'] = $assignees;
    }
    // Lastly, page number. We're doing something different to SMF's normal style here. Long and complicated, but there you go.
    if (isset($_POST['page'])) {
        $context['pagenum'] = (int) $_POST['page'];
    }
    if (empty($context['pagenum']) || $context['pagenum'] < 1) {
        $context['pagenum'] = 1;
    }
    $number_per_page = 20;
    // OK, so are there any words? If not, execute this sucker the quick way and get out to the template quick.
    $context['search_terms'] = !empty($_POST['search']) ? trim($_POST['search']) : '';
    // Also, did we select some text but fail to select what it was searching in? If so, kick it out.
    if (!empty($context['search_terms']) && empty($_POST['search_subjects']) && empty($_POST['search_tickets']) && empty($_POST['search_replies'])) {
        return $context['sub_template'] = 'search_no_results';
    } elseif (!empty($context['search_terms'])) {
        // We're using search terms, and we need to store the areas we're covering. Only makes sense if we're using terms though.
        $context['search_params']['areas'] = array();
        foreach (array('subjects', 'tickets', 'replies') as $area) {
            if (!empty($_POST['search_' . $area])) {
                $context['search_params']['areas'][$area] = true;
            }
        }
        // While we're at it, see if we actually have any words to search for.
        $tokens = shd_tokeniser($context['search_terms']);
        $count_tokens = count($tokens);
        // No actual words?
        if ($count_tokens == 0) {
            $context['search_terms'] = '';
            unset($context['search_params']['areas']);
        }
    }
    // Spam me not!
    if (empty($_SESSION['lastsearch'])) {
        spamProtection('search');
    } else {
        list($temp_clauses, $temp_params, $temp_terms) = unserialize($_SESSION['lastsearch']);
        if ($temp_clauses != $context['search_clauses'] || $temp_params != $context['search_params'] || $temp_terms != $context['search_terms']) {
            spamProtection('search');
        }
    }
    $_SESSION['lastsearch'] = serialize(array($context['search_clauses'], $context['search_params'], $context['search_terms']));
    $context['search_params']['start'] = ($context['pagenum'] - 1) * $number_per_page;
    $context['search_params']['limit'] = $number_per_page;
    if (empty($context['search_terms'])) {
        // This is where it starts to get expensive, *sob*. We first have to query to get the number of applicable rows.
        $query = shd_db_query('', '
			SELECT COUNT(id_ticket)
			FROM {db_prefix}helpdesk_tickets AS hdt
			WHERE ' . implode(' AND ', $context['search_clauses']) . ' LIMIT 1000', $context['search_params']);
        list($count) = $smcFunc['db_fetch_row']($query);
        if ($count == 0) {
            $smcFunc['db_free_result']($query);
            return $context['sub_template'] = 'search_no_results';
        }
        // OK, at least one result, awesome. Are we off the end of the list?
        if ($context['search_params']['start'] > $count) {
            $context['search_params']['start'] = $count - $count % $number_per_page;
            $context['pagenum'] = $context['search_params']['start'] / $number_per_page + 1;
            $context['num_results'] = $count;
        }
        $query = shd_db_query('', '
			SELECT hdt.id_ticket, hdt.id_dept, hdd.dept_name, hdt.subject, hdt.urgency, hdt.private, hdt.last_updated, hdtr.body,
				hdtr.smileys_enabled, hdtr.id_member AS id_member, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name, hdtr.poster_time
			FROM {db_prefix}helpdesk_tickets AS hdt
				INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdt.id_first_msg = hdtr.id_msg)
				INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept)
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = hdtr.id_member)
			WHERE ' . implode(' AND ', $context['search_clauses']) . '
			ORDER BY hdt.last_updated DESC
			LIMIT {int:start}, {int:limit}', $context['search_params']);
        $context['search_results'] = array();
        $page_pos = $context['search_params']['start'];
        // e.g. 0 on page 1, 10 for page 2, the first item will be page_pos + 1, so ++ it before using it.
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $row['result'] = ++$page_pos;
            // Increment first, then use.
            $row['display_id'] = str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT);
            $row['is_ticket'] = true;
            // If we're here, we're only handling tickets anyway. If we're searching text we will need to know if it was a ticket or reply though.
            $row['dept_link'] = !$context['shd_multi_dept'] ? '' : '[<a href="' . $scripturl . '?action=helpdesk;sa=main;dept=' . $row['id_dept'] . '">' . $row['dept_name'] . '</a>] ';
            $context['search_results'][] = $row;
        }
        return $context['sub_template'] = 'search_results';
    } else {
        $context['match_all'] = empty($_POST['searchtype']) || $_POST['searchtype'] == 'all';
        // Then figure out what terms are being matched.
        $matches = array('subjects' => array(), 'messages' => array(), 'id_msg' => array());
        // Doing subjects. Fetch all the instances that match and begin filtering as we go.
        if (!empty($context['search_params']['areas']['subjects'])) {
            $query = shd_db_query('', '
				SELECT hdssw.id_word, hdt.id_first_msg
				FROM {db_prefix}helpdesk_search_subject_words AS hdssw
					INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdssw.id_ticket = hdt.id_ticket)
				WHERE {query_see_ticket}
					AND id_word IN ({array_string:tokens})', array('tokens' => $tokens));
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $matches['subjects'][$row['id_first_msg']][$row['id_word']] = true;
            }
            $smcFunc['db_free_result']($query);
            // Now go through and figure out which tickets we're interested in keeping.
            if ($context['match_all']) {
                foreach ($matches['subjects'] as $msg => $ticket_words) {
                    if (count($ticket_words) != $count_tokens) {
                        // How many words did we match in this subject? If it isn't the number we're expecting, ditch it.
                        unset($matches['subjects'][$msg]);
                    }
                }
            }
            // Now, we just have a list of tickets to play with. Let's put that together in a master list.
            foreach ($matches['subjects'] as $msg => $ticket_words) {
                $matches['id_msg'][$msg] = true;
            }
            unset($matches['subjects']);
        }
        // Now we get the list of words that apply to tickets and replies. The process is different if we do one or both. Both, first.
        if (!empty($context['search_params']['areas']['tickets']) && !empty($context['search_params']['areas']['replies'])) {
            // If we're doing both replies and tickets themselves, we don't have to care too much about the message itself, except for being deleted.
            $query = shd_db_query('', '
				SELECT hdssw.id_word, hdt.id_first_msg
				FROM {db_prefix}helpdesk_search_subject_words AS hdssw
					INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdssw.id_ticket = hdt.id_ticket)
				WHERE {query_see_ticket}
					AND id_word IN ({array_string:tokens})' . (empty($_POST['scope_recycle']) || !shd_allowed_to('shd_access_recyclebin', 0) ? '
					AND hdtr.message_status = {int:not_deleted}' : ''), array('tokens' => $tokens, 'not_deleted' => MSG_STATUS_NORMAL));
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $matches['messages'][$row['id_first_msg']][$row['id_word']] = true;
            }
            $smcFunc['db_free_result']($query);
            if ($context['match_all']) {
                foreach ($matches['messages'] as $msg => $ticket_words) {
                    if (count($ticket_words) != $count_tokens) {
                        // How many words did we match in this subject? If it isn't the number we're expecting, ditch it.
                        unset($matches['messages'][$msg]);
                    }
                }
            }
            // Now, we just have a list of tickets to play with. Let's put that together in a master list.
            foreach ($matches['messages'] as $msg => $ticket_words) {
                $matches['id_msg'][$msg] = true;
            }
            unset($matches['messages']);
        } elseif (!empty($context['search_params']['areas']['tickets']) || !empty($context['search_params']['areas']['replies'])) {
            $query = $smcFunc['db_query']('', '
				SELECT hdstw.id_word, hdstw.id_msg
				FROM {db_prefix}helpdesk_search_ticket_words AS hdstw
					INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdstw.id_msg = hdtr.id_msg)
					INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdtr.id_ticket = hdt.id_ticket)
				WHERE id_word IN ({array_string:tokens})
					AND hdstw.id_msg {raw:operator} hdt.id_first_msg' . (empty($_POST['scope_recycle']) || !shd_allowed_to('shd_access_recyclebin', 0) ? '
					AND hdtr.message_status = {int:not_deleted}' : ''), array('tokens' => $tokens, 'not_deleted' => MSG_STATUS_NORMAL, 'operator' => !empty($context['search_params']['areas']['tickets']) ? '=' : '!='));
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $matches['messages'][$row['id_msg']][$row['id_word']] = true;
            }
            $smcFunc['db_free_result']($query);
            if ($context['match_all']) {
                foreach ($matches['messages'] as $ticket => $ticket_words) {
                    if (count($ticket_words) != $count_tokens) {
                        // How many words did we match in this subject? If it isn't the number we're expecting, ditch it.
                        unset($matches['messages'][$ticket]);
                    }
                }
            }
            // Now, we just have a list of tickets to play with. Let's put that together in a master list.
            foreach ($matches['messages'] as $msg => $ticket_words) {
                $matches['id_msg'][$ticket] = true;
            }
            unset($matches['messages']);
        }
        // Aw, no matches?
        if (empty($matches['id_msg'])) {
            return $context['sub_template'] = 'search_no_results';
        }
        $context['search_clauses'][] = 'hdtr.id_msg IN ({array_int:msg})';
        $context['search_params']['msg'] = array_keys($matches['id_msg']);
        // How many results are there in total?
        $query = shd_db_query('', '
			SELECT COUNT(*)
			FROM {db_prefix}helpdesk_tickets AS hdt
				INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_ticket = hdt.id_ticket)
			WHERE ' . implode(' AND ', $context['search_clauses']) . ' LIMIT 1000', $context['search_params']);
        list($count) = $smcFunc['db_fetch_row']($query);
        if ($count == 0) {
            $smcFunc['db_free_result']($query);
            return $context['sub_template'] = 'search_no_results';
        }
        // OK, at least one result, awesome. Are we off the end of the list?
        if ($context['search_params']['start'] > $count) {
            $context['search_params']['start'] = $count - $count % $number_per_page;
            $context['pagenum'] = $context['search_params']['start'] / $number_per_page + 1;
            $context['num_results'] = $count;
        }
        // Get the results for displaying.
        $query = shd_db_query('', '
			SELECT hdt.id_ticket, hdt.id_dept, hdd.dept_name, hdt.subject, hdt.urgency, hdt.private, hdt.last_updated, hdtr.body,
				hdtr.smileys_enabled, hdtr.id_member AS id_member, IFNULL(mem.real_name, hdtr.poster_name) AS poster_name, hdtr.poster_time,
				hdt.id_first_msg, hdtr.id_msg
			FROM {db_prefix}helpdesk_ticket_replies AS hdtr
				INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = hdtr.id_ticket)
				INNER JOIN {db_prefix}helpdesk_depts AS hdd ON (hdt.id_dept = hdd.id_dept)
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = hdtr.id_member)
			WHERE ' . implode(' AND ', $context['search_clauses']) . '
			ORDER BY hdt.last_updated DESC, hdtr.id_msg DESC
			LIMIT {int:start}, {int:limit}', $context['search_params']);
        $context['search_results'] = array();
        $page_pos = $context['search_params']['start'];
        // e.g. 0 on page 1, 10 for page 2, the first item will be page_pos + 1, so ++ it before using it.
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $row['result'] = ++$page_pos;
            // Increment first, then use.
            $row['display_id'] = str_pad($row['id_ticket'], $modSettings['shd_zerofill'], '0', STR_PAD_LEFT);
            $row['is_ticket'] = $row['id_msg'] == $row['id_first_msg'];
            // If the message we grabbed is the first message, this is actually a ticket, not a reply to one.
            $row['dept_link'] = !$context['shd_multi_dept'] ? '' : '[<a href="' . $scripturl . '?action=helpdesk;sa=main;dept=' . $row['id_dept'] . '">' . $row['dept_name'] . '</a>] ';
            $context['search_results'][] = $row;
        }
        return $context['sub_template'] = 'search_results';
    }
}
/**
 *	Marks a ticket private/not private if the user isn't using Javascript.
 *
 *	Assuming the user can see the ticket and has suitable permissions, the privacy flag will be inverted for the ticket and
 *	updated, as well as updating the action log. If they cannot see the ticket, or do not have privacy-change permission, a fatal
 *	error will be generated.
 *
 *	Accessed through ?action=helpdesk;sa=privacychange;ticket=x;sessvar=sessid before directing back to the ticket page.
 *
 *	@since 1.0
*/
function shd_privacy_change_noajax()
{
    global $smcFunc, $user_info, $context, $sourcedir;
    checkSession('get');
    // First, figure out the state of the ticket - is it private or not? Can we even see it?
    if (empty($context['ticket_id'])) {
        fatal_lang_error('shd_no_ticket', false);
    }
    $query = shd_db_query('', '
		SELECT id_member_started, subject, private, status, id_dept
		FROM {db_prefix}helpdesk_tickets AS hdt
		WHERE {query_see_ticket}
			AND id_ticket = {int:current_ticket}', array('current_ticket' => $context['ticket_id']));
    if ($row = $smcFunc['db_fetch_assoc']($query)) {
        if (in_array($row['status'], array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED)) || !shd_allowed_to('shd_alter_privacy_any', $row['id_dept']) && (!shd_allowed_to('shd_alter_privacy_own', $row['id_dept']) || $row['id_member_started'] != $user_info['id'])) {
            fatal_lang_error('shd_cannot_change_privacy', false);
        }
        $smcFunc['db_free_result']($query);
        $new = empty($row['private']) ? 1 : 0;
        $action = empty($row['private']) ? 'markprivate' : 'marknotprivate';
        require_once $sourcedir . '/sd_source/Subs-SimpleDeskPost.php';
        $msgOptions = array();
        $posterOptions = array();
        $ticketOptions = array('id' => $context['ticket_id'], 'private' => empty($row['private']));
        shd_modify_ticket_post($msgOptions, $ticketOptions, $posterOptions);
        shd_log_action($action, array('ticket' => $context['ticket_id'], 'subject' => $row['subject']));
        redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
    } else {
        fatal_lang_error('shd_no_ticket', false);
    }
}
Ejemplo n.º 22
0
/**
 *	Provides configuration options for the action log.
 *
 *	<ul>
 *	<li>'shd_disable_action_log' (checkbox) - if checked, no actions are added to the action log.</li>
 *	<li>'shd_display_ticket_logs' (checkbox) - if checked, a ticket's specific log is displayed at the foot of the ticket.</li>
 *	<li>'shd_logopt_newposts' (checkbox) - if checked, a ticket's being creation and subsequent replies will be logged.</li>
 *	<li>'shd_logopt_editposts' (checkbox) - if checked, a ticket or its replies being edited will be logged.</li>
 *	<li>'shd_logopt_resolve' (checkbox) - if checked, a ticket's being closed and/or reopened will be logged.</li>
 *	<li>'shd_logopt_autoclose' (checkbox) - if checked, tickets being closed by the helpdesk due to age will be logged.</li>
 *	<li>'shd_logopt_assign' (checkbox) - if checked, a ticket being assigned/reassigned/unassigned will be logged.</li>
 *	<li>'shd_logopt_privacy' (checkbox) - if checked, ticket privacy changes will be logged.</li>
 *	<li>'shd_logopt_urgency' (checkbox) - if checked, ticket urgency changes will be logged.</li>
 *	<li>'shd_logopt_tickettopicmove' (checkbox) - if checked, ticket to topic moves and back will be logged.</li>
 *	<li>'shd_logopt_cfchanges' (checkbox) - if checked, changes to custom fields will be logged.</li>
 *	<li>'shd_logopt_delete' (checkbox) - if checked, ticket/reply deletions (not permadelete) will be logged.</li>
 *	<li>'shd_logopt_restore' (checkbox) - if checked, ticket/reply restores will be logged.</li>
 *	<li>'shd_logopt_permadelete' (checkbox) - if checked, permadeletes will be logged.</li>
 *	<li>'shd_logopt_relationships' (checkbox) - if checked, ticket relationship changes will be logged.</li>
 *	<li>'shd_logopt_move_dept' (checkbox) - if checked, ticket moves between departments will be logged.</li>
 *	<li>'shd_logopt_monitor' (checkbox) - if checked, users adding/removing tickets to/from their monitor lists will be logged.</li>
 *	</ul>
 *
 *	@param bool $return_config Whether to return configuration items or not; this is provided solely for SMF ACP compatibility (it expects to pass bool true in to get a list of options)
 *
 *	@return array An array of items that make up the search options on the given admin page, each item is itself an array of (type, option name/language string, [other related information])
 *	@since 1.0
 *	@see shd_admin_options()
*/
function shd_modify_actionlog_options($return_config)
{
    global $context, $modSettings, $txt;
    $multi_dept = shd_allowed_to('access_helpdesk', false);
    $config_vars = array(array('check', 'shd_disable_action_log', 'javascript' => ' onchange="javascript:switchitems();"'), array('check', 'shd_display_ticket_logs', 'disabled' => !empty($modSettings['shd_disable_action_log'])), '', array('check', 'shd_logopt_newposts', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_editposts', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_resolve', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_autoclose', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('checkall', 'shd_logopt_1', array('shd_logopt_newposts', 'shd_logopt_editposts', 'shd_logopt_resolve', 'shd_logopt_autoclose')), '', array('check', 'shd_logopt_assign', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_privacy', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_urgency', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_tickettopicmove', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_cfchanges', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('checkall', 'shd_logopt_2', array('shd_logopt_assign', 'shd_logopt_privacy', 'shd_logopt_urgency', 'shd_logopt_tickettopicmove', 'shd_logopt_cfchanges')), '', array('check', 'shd_logopt_delete', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_restore', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_permadelete', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('check', 'shd_logopt_relationships', 'disabled' => !empty($modSettings['shd_disable_action_log']) || !empty($modSettings['shd_disable_relationships'])), array('checkall', 'shd_logopt_3', array('shd_logopt_delete', 'shd_logopt_restore', 'shd_logopt_permadelete', 'shd_logopt_relationships')), '', array('check', 'shd_logopt_move_dept', 'disabled' => !empty($modSettings['shd_disable_action_log']) && !empty($multi_dept)), array('check', 'shd_logopt_monitor', 'disabled' => !empty($modSettings['shd_disable_action_log'])), array('checkall', 'shd_logopt_4', array('shd_logopt_move_dept', 'shd_logopt_monitor')));
    $context['settings_title'] = $txt['shd_admin_options_actionlog'];
    $context['settings_icon'] = 'log.png';
    if (empty($context['settings_pre_javascript'])) {
        $context['settings_pre_javascript'] = '';
    }
    $context['settings_pre_javascript'] .= '
		function switchitems()
		{
			var state = document.getElementById("shd_disable_action_log").checked;
			shd_switchable_item("shd_display_ticket_logs", state);
			shd_switchable_item("shd_logopt_newposts", state);
			shd_switchable_item("shd_logopt_editposts", state);
			shd_switchable_item("shd_logopt_resolve", state);
			shd_switchable_item("shd_logopt_autoclose", state);
			shd_switchable_item("shd_logopt_assign", state);
			shd_switchable_item("shd_logopt_privacy", state);
			shd_switchable_item("shd_logopt_urgency", state);
			shd_switchable_item("shd_logopt_tickettopicmove", state);
			shd_switchable_item("shd_logopt_cfchanges", state);
			shd_switchable_item("shd_logopt_delete", state);
			shd_switchable_item("shd_logopt_restore", state);
			shd_switchable_item("shd_logopt_permadelete", state);
			shd_switchable_item("shd_logopt_relationships", state);
			shd_switchable_item("shd_logopt_move_dept", state);
			shd_switchable_item("shd_logopt_monitor", state);
		}';
    call_integration_hook('shd_hook_admin_actionlog', array(&$config_vars, &$return_config));
    return $config_vars;
}