Exemplo n.º 1
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);
    }
}
/**
 *	Updates a ticket's relationships.
 *
 *	This function is responsible for adding, updating and removing relationships.
 *
 *	Accessed through ?action=helpdesk;sa=relation;ticket=x;linkticket=y;relation=[linked|duplicated|parent|child|delete];sessvar=sessid and will redirect back to the ticket once complete.
 *
 *	@since 2.0
*/
function shd_ticket_relation()
{
    global $context, $smcFunc, $modSettings;
    checkSession('request');
    if (!empty($modSettings['shd_disable_relationships'])) {
        fatal_lang_error('shd_relationships_are_disabled', false);
    }
    $otherticket = isset($_REQUEST['otherticket']) ? (int) $_REQUEST['otherticket'] : 0;
    if (empty($context['ticket_id']) || empty($otherticket)) {
        fatal_lang_error('shd_no_ticket', false);
    }
    if ($context['ticket_id'] == $otherticket) {
        fatal_lang_error('shd_cannot_relate_self', false);
    }
    $actions = array('linked', 'duplicated', 'parent', 'child', 'delete');
    $rel_action = isset($_REQUEST['relation']) && in_array($_REQUEST['relation'], $actions) ? $_REQUEST['relation'] : '';
    if (empty($rel_action)) {
        fatal_lang_error('shd_invalid_relation', false);
    }
    // Quick/consistent way to ensure permissions are adhered to and that the ticket exists. Might as well get the subject while here too.
    $ticketinfo = shd_load_ticket($context['ticket_id']);
    $primary_subject = $ticketinfo['subject'];
    $dept = $ticketinfo['dept'];
    $ticketinfo = shd_load_ticket($otherticket);
    $secondary_subject = $ticketinfo['subject'];
    if ($rel_action == 'delete') {
        shd_is_allowed_to('shd_delete_relationships', $dept);
    } else {
        shd_is_allowed_to('shd_create_relationships', $dept);
    }
    // See if there's an existing relationship with these parameters
    $query = shd_db_query('', '
		SELECT rel_type
		FROM {db_prefix}helpdesk_relationships
		WHERE primary_ticket = {int:ticket}
			AND secondary_ticket = {int:otherticket}', array('ticket' => $context['ticket_id'], 'otherticket' => $otherticket));
    $new_relationship = $smcFunc['db_num_rows']($query) == 0;
    list($existing_relation) = $new_relationship ? array(-1) : $smcFunc['db_fetch_row']($query);
    $smcFunc['db_free_result']($query);
    if ($rel_action == 'delete' && $new_relationship) {
        fatal_lang_error('shd_no_relation_delete', false);
    }
    $log_prefix = 'rel_' . ($new_relationship || $rel_action == 'delete' ? '' : 're_');
    $log_map = array('delete' => 'delete', 'linked' => 'linked', 'duplicated' => 'duplicated', 'parent' => 'child', 'child' => 'parent');
    $log_assoc_ids = array('delete' => -1, 'linked' => RELATIONSHIP_LINKED, 'duplicated' => RELATIONSHIP_DUPLICATED, 'parent' => RELATIONSHIP_ISPARENT, 'child' => RELATIONSHIP_ISCHILD);
    $logaction_ticket = $log_prefix . $rel_action;
    $logaction_otherticket = $log_prefix . $log_map[$rel_action];
    // The "from" ticket is $context['ticket_id'], $otherticket is the ticket whose id the user gives, and $rel_action sets the relationship type.
    call_integration_hook('shd_hook_relations', array(&$rel_action, &$otherticket));
    if ($rel_action == 'delete') {
        // Delete the link
        shd_db_query('', '
			DELETE FROM {db_prefix}helpdesk_relationships
			WHERE (primary_ticket = {int:ticket} AND secondary_ticket = {int:otherticket})
				OR (primary_ticket = {int:otherticket} AND secondary_ticket = {int:ticket})', array('ticket' => $context['ticket_id'], 'otherticket' => $otherticket));
    } else {
        $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_relationships', array('primary_ticket' => 'int', 'secondary_ticket' => 'int', 'rel_type' => 'int'), array(array($context['ticket_id'], $otherticket, $log_assoc_ids[$rel_action]), array($otherticket, $context['ticket_id'], $log_assoc_ids[$log_map[$rel_action]])), array('primary_ticket', 'secondary_ticket'));
    }
    // Now actually log it, main ticket first -- if it's different to the one we had before
    if ($log_assoc_ids[$rel_action] != $existing_relation) {
        $params = array('ticket' => $context['ticket_id'], 'otherticket' => $otherticket, 'subject' => $primary_subject, 'othersubject' => $secondary_subject);
        shd_log_action($logaction_ticket, $params);
        $params = array('ticket' => $otherticket, 'otherticket' => $context['ticket_id'], 'subject' => $secondary_subject, 'othersubject' => $primary_subject);
        shd_log_action($logaction_otherticket, $params);
    }
    // See yah
    redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
}
/**
 *	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);
}
Exemplo n.º 4
0
/**
 *	Redirects the user once a ticket has been posted or replied to.
 *
 *	Commits the action log entry for what the user has done (since 1.1), then directs the user based on where they were and what was selected:
 *	- if 'return to ticket' was not selected, return to the front page
 *	- if it was, and we edited a reply, return to the reply
 *	- if it was select, but it was a new topic/reply, return just to the topic itself
 *
 *	@since 1.0
*/
function shd_done_posting()
{
    global $context, $smcFunc, $modSettings, $txt, $scripturl;
    // Do the log stuff
    $context['log_params']['ticket'] = $context['ticket_id'];
    if (!empty($context['ticket_form']['msg'])) {
        $context['log_params']['msg'] = $context['ticket_form']['msg'];
    }
    if (!empty($context['log_action'])) {
        shd_log_action($context['log_action'], $context['log_params']);
    }
    $thank_you = false;
    if (!empty($modSettings['shd_thank_you_post']) && empty($context['ticket_form']['msg'])) {
        // So we're doing a "thanks for posting, here's what's next" message. Well, it's only to new tickets (not on reply) - but... should it go to everyone, or only non staff?
        if (empty($modSettings['shd_thank_you_nonstaff']) || !shd_allowed_to('shd_staff', $context['shd_department'])) {
            $thank_you = true;
            $context['sub_template'] = 'shd_thank_posting';
            $context['page_icon'] = 'log_newticket.png';
            $context['page_title'] = $txt['shd_ticket_posted_header'];
            // Now customise it, including adding the preferences link if appropriate. Note that we don't have to verify they can create new tickets, they wouldn't be here if they couldn't.
            $body = $txt['shd_ticket_posted_body'];
            if (shd_allowed_to(array('shd_view_preferences_own', 'shd_view_preferences_any'), $context['ticket_form']['dept'])) {
                $body .= $txt['shd_ticket_posted_prefs'];
            }
            $body .= $txt['shd_ticket_posted_footer'];
            $replacements = array('{membername}' => $context['user']['name'], '{subject}' => $context['ticket_form']['subject'], '{ticketurl}' => $scripturl . '?action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'], '{forum_name}' => $context['forum_name_html_safe'], '{newticketlink}' => $scripturl . '?action=helpdesk;sa=newticket', '{helpdesklink}' => $scripturl . '?' . $context['shd_home'] . $context['shd_dept_link'], '{forumlink}' => $scripturl, '{prefslink}' => $scripturl . '?action=profile;area=hd_prefs');
            $context['page_body'] = parse_bbc(str_replace(array_keys($replacements), array_values($replacements), $body), true);
        }
    }
    if (!$thank_you) {
        // After all this time... after everything we saw, after everything we lost... I have only one thing to say to you... BYE!
        if (empty($_REQUEST['goback'])) {
            redirectexit($context['shd_home'] . $context['shd_dept_link']);
        } elseif (!empty($context['ticket_form']['msg'])) {
            // IE prior to 9 has issues with the ; in the URL and preserving the # fragment, so we give it & instead.
            if ($context['browser']['is_ie']) {
                redirectexit('action=helpdesk&sa=ticket&ticket=' . $context['ticket_id'] . '.msg' . $context['ticket_form']['msg'] . '#msg' . $context['ticket_form']['msg'], true);
            } else {
                redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . '.msg' . $context['ticket_form']['msg'] . '#msg' . $context['ticket_form']['msg'], false);
            }
        } else {
            redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
        }
    }
}
/**
 *	Action a new assignment via AJAX.
 *
 *	Operations:
 *	- Session check
 * 	- Permissions check (that you can assign a ticket to someone else); if you can't assign a ticket to someone else, bail.
 *	- Get the list of information for a ticket (which implicitly checks ticket access); if you can't see the ticket, bail.
 *	- Get the list of who can be assigned a ticket; if requested user not on that list, bail.
 *	- Update and build return status, and return via AJAX.
 */
function shd_ajax_assign2()
{
    global $context, $smcFunc, $txt, $sourcedir, $user_profile;
    checkSession('get');
    if (!empty($context['ticket_id'])) {
        $query = shd_db_query('', '
			SELECT hdt.private, hdt.id_member_started, id_member_assigned, subject, id_dept, hdt.status, 1 AS valid
			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) {
            list($private, $ticket_starter, $ticket_assigned, $subject, $dept, $status, $valid) = $smcFunc['db_fetch_row']($query);
        }
        $smcFunc['db_free_result']($query);
    }
    if (empty($valid)) {
        return $context['ajax_return'] = array('error' => $txt['shd_no_ticket']);
    }
    if (!isset($_GET['to_user']) || !is_numeric($_GET['to_user'])) {
        return $context['ajax_return'] = array('error' => $txt['shd_assigned_not_permitted'] . 'line459');
    }
    if (!shd_allowed_to('shd_assign_ticket_any', $dept) || $status == TICKET_STATUS_CLOSED || $status == TICKET_STATUS_DELETED) {
        return $context['ajax_return'] = array('error' => $txt['shd_cannot_assign']);
    }
    $_GET['to_user'] = isset($_GET['to_user']) ? (int) $_GET['to_user'] : 0;
    require_once $sourcedir . '/sd_source/SimpleDesk-Assign.php';
    $assignees = shd_get_possible_assignees($private, $ticket_starter, $dept);
    array_unshift($assignees, 0);
    // add the unassigned option in at the start
    if (!in_array($_GET['to_user'], $assignees)) {
        return $context['ajax_return'] = array('error' => $txt['shd_assigned_not_permitted']);
    }
    if (!empty($_GET['to_user'])) {
        loadMemberData($_GET['to_user']);
    }
    $user_name = shd_profile_link(empty($_GET['to_user']) ? '<span class="error">' . $txt['shd_unassigned'] . '</span>' : $user_profile[$_GET['to_user']]['member_name'], $_GET['to_user']);
    // If it's being assigned to the current assignee, don't bother actually requesting the change.
    if ($_GET['to_user'] != $ticket_assigned) {
        $log_params = array('subject' => $subject, 'ticket' => $context['ticket_id'], 'user_id' => $_GET['to_user'], 'user_name' => $user_name);
        shd_log_action('assign', $log_params);
        shd_commit_assignment($context['ticket_id'], $_GET['to_user'], true);
    }
    return $context['ajax_return'] = array('assigned' => $user_name);
}
/**
 *	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);
    }
}
Exemplo n.º 7
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']);
}
Exemplo n.º 8
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']);
}
Exemplo n.º 9
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);
}