/** * Marks a ticket resolved or unresolved. * * This function identifies whether a given ticket is resolved or not, if not resolved, mark it resolved. If it was resolved * reopen the ticket back to an appropriate status based on last respondent. In both cases, the action is logged in the action log. * It is also unassigned from having a user on either closure or reopen. * * Accessed through ?action=helpdesk;sa=resolve;ticket=x;sessvar=sessid before redirecting back to the ticket, or add ;home to the * URL to have it redirect back to the home page. * * @since 1.0 */ function shd_ticket_resolve() { global $smcFunc, $user_info, $context, $sourcedir; checkSession('get'); // First, figure out the state of the ticket - is it resolved or not? Can we even see it? if (empty($context['ticket_id'])) { fatal_lang_error('shd_no_ticket', false); } $context['shd_return_to'] = isset($_REQUEST['home']) ? 'home' : 'ticket'; $query = shd_db_query('', ' SELECT id_member_started, id_member_updated, status, num_replies, subject, 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)) { $smcFunc['db_free_result']($query); $action = $row['status'] != TICKET_STATUS_CLOSED ? 'resolve' : 'unresolve'; call_integration_hook('shd_hook_mark' . $action); if (!shd_allowed_to('shd_' . $action . '_ticket_any', $row['id_dept']) && (!shd_allowed_to('shd_' . $action . '_ticket_own', $row['id_dept']) || $row['id_member_started'] != $user_info['id'])) { fatal_lang_error('shd_cannot_' . $action, false); } // OK, so what about any children related tickets that are still open? Eeek, could be awkward. if (empty($modSettings['shd_disable_relationships'])) { $query = shd_db_query('', ' SELECT COUNT(hdt.id_ticket) FROM {db_prefix}helpdesk_relationships AS rel INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (rel.secondary_ticket = hdt.id_ticket) WHERE rel.primary_ticket = {int:ticket} AND rel.rel_type = {int:parent} AND hdt.status NOT IN ({array_int:closed_status})', array('ticket' => $context['ticket_id'], 'parent' => RELATIONSHIP_ISPARENT, 'closed_status' => array(TICKET_STATUS_CLOSED, TICKET_STATUS_DELETED))); list($count_children) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); if (!empty($count_children)) { fatal_lang_error('error_shd_cannot_resolve_children', false); } } $new = shd_determine_status($action, $row['id_member_started'], $row['id_member_updated'], $row['num_replies'], $row['id_dept']); shd_db_query('', ' UPDATE {db_prefix}helpdesk_tickets SET status = {int:status} WHERE id_ticket = {int:ticket}', array('status' => $new, 'ticket' => $context['ticket_id'])); shd_log_action($action, array('ticket' => $context['ticket_id'], 'subject' => $row['subject'])); shd_clear_active_tickets($row['id_dept']); if ($context['shd_return_to'] == 'home') { redirectexit($context['shd_home'] . $context['shd_dept_link']); } else { redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']); } } else { fatal_lang_error('shd_no_ticket', false); } }
function shd_scheduled_close_tickets() { global $modSettings, $smcFunc, $txt; @set_time_limit(600); // Ten minutes. Is a big job, possibly. // 1. Get the list of tickets. $query = $smcFunc['db_query']('', ' SELECT hdt.id_ticket, hdt.subject, hdt.id_member_started, hdt.id_member_updated, hdt.id_dept FROM {db_prefix}helpdesk_depts AS hdd INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdd.id_dept = hdt.id_dept) WHERE hdd.autoclose_days > 0 AND hdt.last_updated <= {int:time} - (86400 * hdd.autoclose_days) AND hdt.status IN ({array_int:open})', array('open' => array(0, 1, 2), 'time' => time())); $tickets = array(); $subjects = array(); $members = array(); $depts = array(); while ($row = $smcFunc['db_fetch_assoc']($query)) { $tickets[$row['id_ticket']] = $row['id_ticket']; $subjects[$row['id_ticket']] = $row['subject']; $members[] = $row['id_member_started']; $members[] = $row['id_member_updated']; $depts[$row['id_dept']] = $row['id_dept']; } $smcFunc['db_free_result']($query); // Any to do? if (!empty($tickets)) { $time = time(); // 2. Update the tickets. $smcFunc['db_query']('', ' UPDATE {db_prefix}helpdesk_tickets SET status = {int:closed}, last_updated = {int:time} WHERE id_ticket IN ({array_int:tickets})', array('closed' => 3, 'tickets' => $tickets, 'time' => $time)); // 3. Update the log if appropriate. Normally we would call shd_log_action(), however here... we might be doing a lot, so instead, we do it manually ourselves. if (empty($modSettings['shd_disable_action_log']) && !empty($modSettings['shd_logopt_autoclose'])) { $rows = array(); foreach ($tickets as $ticket) { $rows[] = array($time, 0, '', 'autoclose', $ticket, 0, serialize(array('subject' => $subjects[$ticket], 'auto' => true))); } $smcFunc['db_insert']('', '{db_prefix}helpdesk_log_action', array('log_time' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string', 'id_ticket' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534'), $rows, array('id_action')); } // 4. If caching is enabled, make sure to purge the cache for members so their number of tickets will be recalculated. // No need to dump all SD cache items though, though we have to get all those whose tickets were affected, plus all staff. $depts = array_flip($depts); foreach ($depts as $dept) { shd_clear_active_tickets($dept); } } }
/** * Updates a ticket/reply item in the database. * * This function allows modification of all post/ticket details - and can be used independently; it is possible (and even done * in SimpleDesk) to update just a ticket or just a post from this function. All three parameters are by <b>reference</b> * meaning they WILL be updated if things change. Note that this function is not validating that they are sensible values; it is * up to the calling function to ascertain that. * * @param array &$msgOptions - a hash array by reference, stating zero or more details to change on a message (if the change is strictly ticket-only, the entire $msgOptions array can be an empty array): * <ul> * <li>id: Required if changing a message; the principle numeric id of the message to modify</li> * <li>body: Optional, the principle body content of the message to change; if omitted, no change will occur. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and preparsecode)</li> * <li>modified: Optional, hash array containing items relating to modification (if 'modified' key exists, all of these should be set) * <ul> * <li>time: Unsigned int timestamp of the change</li> * <li>name: String; user name of the user making the change</li> * <li>id: Unsigned int user id of the user making the change</li> * </ul> * </li> * <li>smileys_enabled: Optional, boolean denoting whether smileys should be active on this post; if omitted no change will occur</li> * <li>attachments: Optional, array of attachment ids that need attaching to this message; if omitted no changes will occur</li> * </ul> * * @param array &$ticketOptions - a hash array by reference, stating one or more details necessary to change on a ticket: * <ul> * <li>id: Required in all cases, numeric ticket id that the edit relates to</li> * <li>subject: Optional string with the new subject in; if omitted no change will occur. If set, assumed to have been cleaned already (with $smcFunc['htmlspecialchars'] and strtr)</li> * <li>urgency: Optional integer with the new urgency in; if omitted no change will occur</li> * <li>status: Optional integer with the new status in; if omitted no change will occur</li> * <li>ssigned: Optional integer with the user id of assigned user; if omitted no change will occur (note, you would declare this as 0 to unassign a ticket - set to 0 is not omitted)</li> * <li>private: Optional boolean as to privacy of ticket: true = private, false = not private (note, you still declare this to change it)</li> * </ul> * * @param array &$posterOptions - a hash array by reference of details to change on the poster of a message: * <ul> * <li>name: Optional string, name of credited poster (in absence of id, this will be used); if omitted no change will occur</li> * <li>email: Optional string, email address of poster; if omitted no change will occur</li> * </ul> * * @return bool True on success, false on failure. * @since 1.0 */ function shd_modify_ticket_post(&$msgOptions, &$ticketOptions, &$posterOptions) { global $user_info, $txt, $modSettings, $smcFunc, $context; $messages_columns = array(); $ticket_columns = array(); $ticketOptions['id'] = !empty($ticketOptions['id']) ? (int) $ticketOptions['id'] : 0; if ($ticketOptions['id'] == 0) { return false; } if (isset($posterOptions['name'])) { $messages_columns['poster_name'] = $posterOptions['name']; } if (isset($posterOptions['email'])) { $messages_columns['poster_email'] = $posterOptions['email']; } if (isset($msgOptions['body'])) { $messages_columns['body'] = $msgOptions['body']; } if (!empty($msgOptions['modified'])) { $messages_columns['modified_time'] = $msgOptions['modified']['time']; $messages_columns['modified_name'] = $msgOptions['modified']['name']; $messages_columns['modified_member'] = $msgOptions['modified']['id']; } if (isset($msgOptions['smileys_enabled'])) { $messages_columns['smileys_enabled'] = empty($msgOptions['smileys_enabled']) ? 0 : 1; } if (isset($ticketOptions['subject'])) { $ticket_columns['subject'] = $ticketOptions['subject']; } if (isset($ticketOptions['status'])) { $ticket_columns['status'] = $ticketOptions['status']; } if (isset($ticketOptions['urgency'])) { $ticket_columns['urgency'] = $ticketOptions['urgency']; } if (isset($ticketOptions['assigned'])) { $ticket_columns['id_member_assigned'] = $ticketOptions['assigned']; } if (isset($ticketOptions['private'])) { $ticket_columns['private'] = empty($ticketOptions['private']) ? 0 : 1; } // Fix the attachments. if (!empty($msgOptions['attachments'])) { $array = array(); foreach ($msgOptions['attachments'] as $attach) { $array[] = array($attach, $msgOptions['id'], $ticketOptions['id']); } $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_msg' => 'int', 'id_ticket' => 'int'), $array, array('id_attach')); } if (empty($messages_columns) && empty($ticket_columns) && empty($ticketOptions['custom_fields']) && empty($msgOptions['custom_fields'])) { return true; } // It's do or die time: forget any user aborts! $previous_ignore_user_abort = ignore_user_abort(true); // OK, let's get all this set up ready for SQL magic // Which columns need to be ints? $messageInts = array('modified_time', 'modified_member', 'smileys_enabled'); $msg_update_parameters = array('id_msg' => empty($msgOptions['id']) ? 0 : (int) $msgOptions['id']); foreach ($messages_columns as $var => $val) { $messages_columns[$var] = $var . ' = {' . (in_array($var, $messageInts) ? 'int' : 'string') . ':var_' . $var . '}'; $msg_update_parameters['var_' . $var] = $val; } $ticketInts = array('status', 'urgency'); $ticket_update_parameters = array('id_ticket' => $ticketOptions['id']); foreach ($ticket_columns as $var => $val) { $ticket_columns[$var] = $var . ' = {' . (in_array($var, $ticketInts) ? 'int' : 'string') . ':var_' . $var . '}'; $ticket_update_parameters['var_' . $var] = $val; } // GO GO GO! (message first) if (!empty($messages_columns)) { shd_db_query('', ' UPDATE {db_prefix}helpdesk_ticket_replies SET ' . implode(', ', $messages_columns) . ' WHERE id_msg = {int:id_msg}', $msg_update_parameters); } if (!empty($ticket_columns)) { shd_db_query('', ' UPDATE {db_prefix}helpdesk_tickets SET ' . implode(', ', $ticket_columns) . ' WHERE id_ticket = {int:id_ticket}', $ticket_update_parameters); } // And fix unread list if (!empty($msgOptions['modified'])) { shd_db_query('', ' UPDATE {db_prefix}helpdesk_log_read SET id_msg = {int:last_msg} WHERE id_member != {int:modified_member} AND id_ticket = {int:ticket} AND id_msg >= {int:edited_msg}', array('last_msg' => $msg_update_parameters['id_msg'] - 1, 'modified_member' => $msgOptions['modified']['id'], 'ticket' => $ticketOptions['id'], 'edited_msg' => $msg_update_parameters['id_msg'])); } // Are we updating custom fields? $rows = array(); $context['custom_fields_updated'] = array(); if (!empty($ticketOptions['custom_fields'])) { // Some may be pre-existing, some may need purging. foreach ($ticketOptions['custom_fields'] as $field_id => $field) { // No new value, or new value is the same as the old one. if (!isset($field['new_value']) || isset($field['value']) && $field['value'] == $field['new_value']) { continue; } // So we have a new value, or a changed value. If it's changed, but changed to default, mark it as default $rows[] = array('id_post' => $ticketOptions['id'], 'id_field' => $field_id, 'value' => $field['new_value'], 'post_type' => CFIELD_TICKET); if ($field['type'] == CFIELD_TYPE_MULTI) { $values = array(); if (!empty($field['value'])) { foreach ($field['value'] as $value) { if (!empty($value)) { $values[] = $field['options'][$value]; } } } $oldvalue = implode(', ', $values); $values = array(); $newvalues = explode(',', $field['new_value']); foreach ($newvalues as $value) { if (!empty($value)) { $values[] = $field['options'][$value]; } } $newvalue = implode(', ', $values); } else { $oldvalue = !empty($field['value']) && ($field['type'] == CFIELD_TYPE_RADIO || $field['type'] == CFIELD_TYPE_SELECT) ? $field['options'][$field['value']] : (empty($field['value']) ? '' : $field['value']); $newvalue = !empty($field['new_value']) && ($field['type'] == CFIELD_TYPE_RADIO || $field['type'] == CFIELD_TYPE_SELECT) ? $field['options'][$field['new_value']] : $field['new_value']; } $context['custom_fields_updated'][] = array('ticket' => $ticketOptions['id'], 'fieldname' => $field['name'], 'oldvalue' => $oldvalue, 'newvalue' => $newvalue, 'scope' => CFIELD_TICKET, 'visible' => $field['visible'], 'fieldtype' => $field['type']); if ($field['new_value'] == $field['default_value']) { $context['custom_fields_updated'][count($context['custom_fields_updated']) - 1]['default'] = true; } } } // Same deal, this time for message options. See above for comments. if (!empty($msgOptions['custom_fields'])) { foreach ($msgOptions['custom_fields'] as $field_id => $field) { if (!isset($field['new_value']) || isset($field['value']) && $field['value'] == $field['new_value']) { continue; } $rows[] = array('id_post' => $msgOptions['id'], 'id_field' => $field_id, 'value' => $field['new_value'], 'post_type' => CFIELD_REPLY); if ($field['type'] == CFIELD_TYPE_MULTI) { $values = array(); if (!empty($field['value'])) { foreach ($field['value'] as $value) { if (!empty($value)) { $values[] = $field['options'][$value]; } } } $oldvalue = implode(', ', $values); $values = array(); $newvalues = explode(',', $field['new_value']); foreach ($newvalues as $value) { if (!empty($value)) { $values[] = $field['options'][$value]; } } $newvalue = implode(', ', $values); } else { $oldvalue = !empty($field['value']) && ($field['type'] == CFIELD_TYPE_RADIO || $field['type'] == CFIELD_TYPE_SELECT) ? $field['options'][$field['value']] : (empty($field['value']) ? $field['type'] != CFIELD_TYPE_LARGETEXT ? $field['default_value'] : '' : $field['value']); $newvalue = !empty($field['new_value']) && ($field['type'] == CFIELD_TYPE_RADIO || $field['type'] == CFIELD_TYPE_SELECT) ? $field['options'][$field['new_value']] : $field['new_value']; } if ($oldvalue != $newvalue) { $context['custom_fields_updated'][] = array('ticket' => $ticketOptions['id'], 'msg' => $msgOptions['id'], 'fieldname' => $field['name'], 'oldvalue' => $oldvalue, 'newvalue' => $newvalue, 'scope' => CFIELD_REPLY, 'visible' => $field['visible'], 'fieldtype' => $field['type']); if ($field['new_value'] == $field['default_value']) { $context['custom_fields_updated'][count($context['custom_fields_updated']) - 1]['default'] = true; } } } } // If there are rows to add or update, commence. if (!empty($rows)) { $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_custom_fields_values', array('id_post' => 'int', 'id_field' => 'int', 'value' => 'string-65534', 'post_type' => 'int'), $rows, array('id_post', 'id_field')); } // Int hook call_integration_hook('shd_hook_modpost', array(&$msgOptions, &$ticketOptions, &$posterOptions)); ignore_user_abort($previous_ignore_user_abort); if (empty($ticketOptions['dept']) && !empty($ticketOptions['id'])) { // So we're making a reply, we need the department id. The ticket will already exist - we just added to it! $query = $smcFunc['db_query']('', ' SELECT id_dept FROM {db_prefix}helpdesk_tickets WHERE id_ticket = {int:id_ticket}', array('id_ticket' => $ticketOptions['id'])); list($ticketOptions['dept']) = $smcFunc['db_fetch_row']($query); $smcFunc['db_free_result']($query); } if (!empty($ticketOptions['dept'])) { shd_clear_active_tickets($ticketOptions['dept']); } // Success. return true; }
/** * Receives the form for moving tickets to topics, and actually handles the move. * * After checking permissions, and so on, begin to actually move posts. * * This is done by invoking SMF's createPost function to make the new thread and repost all the ticket's posts as new thread posts * using defaults for some settings. * * Operations: * - check the user can see the board they are linking to * - move the ticket's text as the opening post * - update the ticket row if the post was modified before * - get the rest of the replies * - step through and post, updating for modified details * - send the notification PM if we're doing that * - update the attachments table * - update the action log * - remove the ticket from the DB * * @see shd_tickettotopic() * @since 1.0 */ function shd_tickettotopic2() { global $smcFunc, $context, $txt, $modSettings, $scripturl, $sourcedir; checkSession(); checkSubmitOnce('check'); if (empty($context['ticket_id'])) { fatal_lang_error('shd_no_ticket'); } if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) { checkSubmitOnce('free'); 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']); } require_once $sourcedir . '/Subs-Post.php'; // The destination board must be numeric. $_POST['toboard'] = (int) $_POST['toboard']; $msg_assoc = array(); // This is complex, very complex. Hopefully 5 minutes will be enough... @set_time_limit(300); // Make sure they can see the board they are trying to move to (and get whether posts count in the target board). $request = shd_db_query('', ' SELECT b.count_posts, b.name, hdt.subject, hdt.id_member_started, hdtr.body, hdt.id_first_msg, hdtr.smileys_enabled, hdtr.modified_time, hdtr.modified_name, hdtr.poster_time, hdtr.id_msg, hdt.deleted_replies, hdt.id_dept FROM {db_prefix}boards AS b INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = {int:ticket}) INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hdt.id_first_msg) WHERE {query_see_board} AND {query_see_ticket} AND b.id_board = {int:to_board} AND b.redirect = {string:blank_redirect} LIMIT 1', array('ticket' => $context['ticket_id'], 'to_board' => $_POST['toboard'], 'blank_redirect' => '')); if ($smcFunc['db_num_rows']($request) == 0) { fatal_lang_error('no_board'); } else { list($pcounter, $board_name, $subject, $owner, $body, $firstmsg, $smileys_enabled, $modified_time, $modified_name, $time, $shd_id_msg, $deleted_replies, $dept) = $smcFunc['db_fetch_row']($request); } $smcFunc['db_free_result']($request); if (!shd_allowed_to('shd_ticket_to_topic', $dept) || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) { fatal_lang_error('shd_cannot_move_ticket', false); } // Are we changing the subject? $old_subject = $subject; $subject = !empty($_POST['change_subject']) && !empty($_POST['subject']) ? $_POST['subject'] : $subject; $context['deleted_prompt'] = false; // Hang on... are there any deleted replies? if ($deleted_replies > 0) { if (shd_allowed_to('shd_access_recyclebin')) { $dr_opts = array('abort', 'delete', 'undelete'); $context['deleted_prompt'] = isset($_REQUEST['deleted_replies']) && in_array($_REQUEST['deleted_replies'], $dr_opts) ? $_REQUEST['deleted_replies'] : 'abort'; } else { fatal_lang_error('shd_cannot_move_ticket_with_deleted'); } } if (!empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'abort') { redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . ';recycle'); } // Now the madness that is custom fields. First, load the custom fields we might/will be using. $query = $smcFunc['db_query']('', ' SELECT hdcf.id_field, hdcf.field_name, hdcf.field_order, hdcf.field_type, hdcf.can_see, hdcf.field_options, hdcf.bbc, hdcf.placement FROM {db_prefix}helpdesk_custom_fields_depts AS hdd INNER JOIN {db_prefix}helpdesk_custom_fields AS hdcf ON (hdd.id_field = hdcf.id_field) WHERE hdd.id_dept = {int:dept} AND hdcf.active = {int:active} ORDER BY hdcf.field_order', array('dept' => $dept, 'active' => 1)); $context['custom_fields'] = array(); $is_staff = shd_allowed_to('shd_staff', $dept); $is_admin = shd_allowed_to('admin_helpdesk', $dept); while ($row = $smcFunc['db_fetch_assoc']($query)) { list($user_see, $staff_see) = explode(',', $row['can_see']); $context['custom_fields'][$row['id_field']] = array('id_field' => $row['id_field'], 'name' => $row['field_name'], 'type' => $row['field_type'], 'bbc' => !empty($row['bbc']), 'options' => !empty($row['field_options']) ? unserialize($row['field_options']) : array(), 'placement' => $row['placement'], 'visible' => array('user' => $user_see, 'staff' => $staff_see, 'admin' => true), 'values' => array()); } $smcFunc['db_free_result']($query); // Having got all the possible fields for this ticket, let's fetch the values for it. That way if we don't have any values for a field, we don't have to care about showing the user. // But first, we need all the message ids. $context['ticket_messages'] = array(); $query = $smcFunc['db_query']('', ' SELECT id_msg FROM {db_prefix}helpdesk_ticket_replies AS hdtr WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); while ($row = $smcFunc['db_fetch_row']($query)) { $context['ticket_messages'][] = $row[0]; } $smcFunc['db_free_result']($query); // Now get a reference for the field values. $query = $smcFunc['db_query']('', ' SELECT cfv.id_post, cfv.id_field, cfv.post_type, cfv.value FROM {db_prefix}helpdesk_custom_fields_values AS cfv WHERE (cfv.id_post = {int:ticket} AND cfv.post_type = 1)' . (!empty($context['ticket_messages']) ? ' OR (cfv.id_post IN ({array_int:msgs}) AND cfv.post_type = 2)' : ''), array('ticket' => $context['ticket_id'], 'msgs' => $context['ticket_messages'])); while ($row = $smcFunc['db_fetch_assoc']($query)) { if (isset($context['custom_fields'][$row['id_field']])) { $context['custom_fields'][$row['id_field']]['values'][$row['post_type']][$row['id_post']] = $row['value']; } } $smcFunc['db_free_result']($query); // Having now established what fields we do actually have values for, let's proceed to deal with them. foreach ($context['custom_fields'] as $field_id => $field) { // Didn't we have any values? If not, prune it, not interested. if (empty($field['values'])) { unset($context['custom_fields'][$field_id]); } // If the user is an administrator, they can always see the fields. if ($is_admin) { // But users might not be able to, in which case we need to validate that actually, they did need to authorise this one. if (!$field['visible']['user'] || !$field['visible']['staff']) { $context['custom_fields_warning'] = true; } } elseif ($is_staff) { // So they're staff. But the field might not be visible to them; they can't deal with it whatever. if (!$field['visible']['staff']) { fatal_lang_error('cannot_shd_move_ticket_topic_hidden_cfs', false); } elseif (!$field['visible']['user']) { $context['custom_fields_warning'] = true; } } else { // Non staff aren't special. They should not be able to make this decision. If someone can't see it, they don't get to make the choice. if (!$field['visible']['user'] || !$field['visible']['staff']) { fatal_lang_error('cannot_shd_move_ticket_topic_hidden_cfs', false); } } // Are we ignoring this field? If so, we can now safely get rid of it at this very point. if (isset($_POST['field' . $field_id]) && $_POST['field' . $field_id] == 'lose') { unset($context['custom_fields'][$field_id]); } } // Were there any special fields? We need to check - and check that they ticked the right box! if (!empty($context['custom_fields_warning']) && empty($_POST['accept_move'])) { checkSubmitOnce('free'); fatal_lang_error('shd_ticket_move_reqd_nonselected', false); } // Just before we do this, make sure we call any hooks. $context has lots of interesting things, as does $_POST. call_integration_hook('shd_hook_tickettotopic'); // OK, so we have some fields, and we're doing something with them. First we need to attach the fields from the ticket to the opening post. shd_append_custom_fields($body, $context['ticket_id'], CFIELD_TICKET); // All okay, it seems. Let's go create the topic. $msgOptions = array('subject' => $subject, 'body' => $body, 'icon' => 'xx', 'smileys_enabled' => !empty($smileys_enabled) ? 1 : 0); $topicOptions = array('board' => $_POST['toboard'], 'lock_mode' => 0, 'mark_as_read' => false); $posterOptions = array('id' => $owner, 'update_post_count' => empty($pcounter)); createPost($msgOptions, $topicOptions, $posterOptions); // Keep track of SHD msg id to SMF msg id $msg_assoc[$shd_id_msg] = $msgOptions['id']; // createPost() doesn't handle modified time and name, so we'll fix that here, along with the poster time. if (!empty($modified_time)) { shd_db_query('', ' UPDATE {db_prefix}messages SET modified_time = {int:modified_time}, modified_name = {string:modified_name}, poster_time = {int:poster_time} WHERE id_msg = {int:id_msg}', array('id_msg' => $firstmsg, 'modified_time' => $modified_time, 'modified_name' => $modified_name, 'poster_time' => $time)); } // Topic created, let's dig out the replies and post them in the topic, if there are any. if (isset($topicOptions['id'])) { $request = shd_db_query('', ' SELECT body, id_member, poster_time, poster_name, poster_email, poster_ip, smileys_enabled, modified_time, modified_member, modified_name, poster_time, id_msg, message_status FROM {db_prefix}helpdesk_ticket_replies AS hdtr WHERE id_ticket = {int:ticket} AND id_msg > {int:ticket_msg} ORDER BY id_msg', array('ticket' => $context['ticket_id'], 'ticket_msg' => $firstmsg)); // The ID of the topic we created $topic = $topicOptions['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)) { if ($row['message_status'] == MSG_STATUS_DELETED && !empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'delete') { // we don't want these replies! continue; } shd_append_custom_fields($row['body'], $row['id_msg'], CFIELD_REPLY); $msgOptions = array('subject' => $txt['response_prefix'] . $subject, 'body' => $row['body'], 'icon' => 'xx', 'smileys_enabled' => !empty($row['smileys_enabled']) ? 1 : 0); $topicOptions = array('id' => $topic, 'board' => $_POST['toboard'], 'lock_mode' => 0, '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'] : '', 'update_post_count' => empty($pcounter)); createPost($msgOptions, $topicOptions, $posterOptions); // Don't forget to note what id $msg_assoc[$row['id_msg']] = $msgOptions['id']; // Meh, createPost() doesn't have any hooks for modified time and user. Let's fix that now. if (!empty($row['modified_time'])) { shd_db_query('', ' UPDATE {db_prefix}messages SET modified_time = {int:modified_time}, modified_name = {string:modified_name}, poster_time = {int:poster_time} WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'], 'modified_time' => $row['modified_time'], 'modified_name' => $row['modified_name'], 'poster_time' => $row['poster_time'])); } } } // Topic: check; Replies: check; Notfiy the ticket starter, if desired. if (isset($_POST['send_pm'])) { $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, '{board}' => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', '{link}' => $scripturl . '?topic=' . $topic . '.0'); $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'], un_htmlspecialchars($message)); } // Right, time to do all the attachment fussing too if (!empty($msg_assoc)) { $attachIDs = array(); $query = shd_db_query('', ' SELECT id_attach, id_msg FROM {db_prefix}helpdesk_attachments WHERE id_msg IN ({array_int:msgs})', array('msgs' => array_keys($msg_assoc))); while ($row = $smcFunc['db_fetch_assoc']($query)) { $attachIDs[] = $row; } $smcFunc['db_free_result']($query); if (!empty($attachIDs)) { // 1. Update all the attachments in the master table; this is the bit that hurts since it can't be done without // a query per row :( foreach ($attachIDs as $attach) { shd_db_query('', ' UPDATE {db_prefix}attachments SET id_msg = {int:new_msg} WHERE id_attach = {int:attach}', array('attach' => $attach['id_attach'], 'new_msg' => $msg_assoc[$attach['id_msg']])); } // 2. Remove the entries from the SD table since we don't need them no more shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_attachments WHERE id_msg IN ({array_int:msgs})', array('msgs' => array_keys($msg_assoc))); } } // Well, it's possible there are some phantom attachments on deleted replies that need to disappear if (!empty($context['deleted_replies']) && $context['deleted_replies'] == 'delete') { $query = shd_db_query('', ' SELECT id_msg FROM {db_prefix}helpdesk_attachments AS hda INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg) WHERE id_ticket = {int:ticket} AND hdtr.message_status = {int:deleted}', array('ticket' => $context['ticket_id'], 'deleted' => MSG_STATUS_DELETED)); if ($smcFunc['db_num_rows']($query) > 0) { $msgs = array(); while ($row = $smcFunc['db_fetch_row']($query)) { $msgs[] = $row[0]; } if (!empty($msgs)) { // Get rid of the parents require_once $sourcedir . '/ManageAttachments.php'; $attachmentQuery = array('attachment_type' => 0, 'id_msg' => 0, 'id_attach' => $msgs); removeAttachments($attachmentQuery); // Get rid of the remainder in hda table shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_attachments WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); } } $smcFunc['db_free_result']($query); } // Now we'll add this to the log. $log_params = array('subject' => $subject, 'board_id' => $_POST['toboard'], 'board_name' => $board_name, 'ticket' => $topic); shd_log_action('tickettotopic', $log_params); // Lastly, delete the ticket from the database. shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_tickets WHERE id_ticket = {int:ticket} LIMIT 1', array('ticket' => $context['ticket_id'])); // And the replies, too. shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_ticket_replies WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id'])); // And custom fields. shd_db_query('', ' DELETE FROM {db_prefix}helpdesk_custom_fields_values WHERE (id_post = {int:ticket} AND post_type = 1)' . (!empty($context['ticket_messages']) ? ' OR (id_post IN ({array_int:msgs}) AND post_type = 2)' : ''), array('ticket' => $context['ticket_id'], 'msgs' => $context['ticket_messages'])); } else { fatal_lang_error('shd_move_topic_not_created', false); } // Clear our cache shd_clear_active_tickets($dept); // Send them to the topic. redirectexit('topic=' . $topic . '.0'); }
/** * Handles AJAX updates to privacy. * * Receives a request via ?action=helpdesk;sa=ajax;op=privacy to flip the privacy setting. * * Operations: * - silent session check; if fail, add to $context['ajax_return']['error'] * - ticket id check; if fail, add to $context['ajax_return']['error'] * - get enough ticket data to do this * - check if the ticket is not able to be updated (either is closed/deleted, or insufficient permissions); if fail add to $context['ajax_return']['error'] * - switch privacy, update database * - clear the cache of tickets for the Helpdesk menu item * - return $context['ajax_return']['message'] as the new privacy item */ function shd_ajax_privacy() { global $smcFunc, $user_info, $context, $txt, $sourcedir; $session_check = checkSession('get', '', false); // check the session but don't die fatally. if (!empty($session_check)) { $context['ajax_return'] = array('error' => $txt[$session_check]); return; } // First, figure out the state of the ticket - is it private or not? Can we even see it? if (empty($context['ticket_id'])) { $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); return; } $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'])) { $context['ajax_return'] = array('error' => $txt['shd_cannot_change_privacy']); return; } $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'])); // Make sure we recalculate the number of tickets on next page load shd_clear_active_tickets($row['id_dept']); $context['ajax_return'] = array('message' => $new ? $txt['shd_ticket_private'] : $txt['shd_ticket_notprivate']); } else { $context['ajax_return'] = array('error' => $txt['shd_no_ticket']); return; } }
/** * 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); } }
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']); }
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); }