function getRequestStructure($format, $data = null) { $supported = array("alert", "autorespond", "source", "topicId", "attachments" => array("*" => array("name", "type", "data", "encoding", "size")), "message", "ip", "priorityId"); # Fetch dynamic form field names for the given help topic and add # the names to the supported request structure if (isset($data['topicId']) && ($topic = Topic::lookup($data['topicId'])) && ($form = $topic->getForm())) { foreach ($form->getDynamicFields() as $field) { $supported[] = $field->get('name'); } } # Ticket form fields # TODO: Support userId for existing user if ($form = TicketForm::getInstance()) { foreach ($form->getFields() as $field) { $supported[] = $field->get('name'); } } # User form fields if ($form = UserForm::getInstance()) { foreach ($form->getFields() as $field) { $supported[] = $field->get('name'); } } if (!strcasecmp($format, 'email')) { $supported = array_merge($supported, array('header', 'mid', 'emailId', 'to-email-id', 'ticketId', 'reply-to', 'reply-to-name', 'in-reply-to', 'references', 'thread-type', 'flags' => array('bounce', 'auto-reply', 'spam', 'viral'), 'recipients' => array('*' => array('name', 'email', 'source')))); $supported['attachments']['*'][] = 'cid'; } return $supported; }
static function dumpTickets($sql, $how = 'csv') { // Add custom fields to the $sql statement $cdata = $fields = $select = array(); foreach (TicketForm::getInstance()->getFields() as $f) { // Ignore core fields if (in_array($f->get('name'), array('subject', 'priority'))) { continue; } elseif (!$f->hasData() || $f->isPresentationOnly()) { continue; } $name = $f->get('name') ? $f->get('name') : 'field_' . $f->get('id'); $key = '__field_' . $f->get('id'); // Fetch ID values for ID-based data if ($f->hasIdValue()) { $name .= '_id'; } $cdata[$key] = $f->get('label'); $fields[$key] = $f; $select[] = "cdata.`{$name}` AS __field_" . $f->get('id'); } if ($select) { $sql = str_replace(' FROM ', ',' . implode(',', $select) . ' FROM ', $sql); } return self::dumpQuery($sql, array('number' => 'Ticket Number', 'created' => 'Date', 'subject' => 'Subject', 'name' => 'From', 'email' => 'From Email', 'priority_desc' => 'Priority', 'dept_name' => 'Department', 'helptopic' => 'Help Topic', 'source' => 'Source', 'status' => 'Current Status', 'effective_date' => 'Last Updated', 'duedate' => 'Due Date', 'isoverdue' => 'Overdue', 'isanswered' => 'Answered', 'assigned' => 'Assigned To', 'staff' => 'Staff Assigned', 'team' => 'Team Assigned', 'thread_count' => 'Thread Count', 'attachments' => 'Attachment Count') + $cdata, $how, array('modify' => function (&$record, $keys) use($fields) { foreach ($fields as $k => $f) { if (($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } return $record; })); }
function validate(&$data, $format, $strict = true) { global $ost; //Call parent to Validate the structure if (!parent::validate($data, $format, $strict) && $strict) { $this->exerr(400, __('Unexpected or invalid data received')); } // Use the settings on the thread entry on the ticket details // form to validate the attachments in the email $tform = TicketForm::objects()->one()->getForm(); $messageField = $tform->getField('message'); $fileField = $messageField->getWidget()->getAttachments(); // Nuke attachments IF API files are not allowed. if (!$messageField->isAttachmentsEnabled()) { $data['attachments'] = array(); } //Validate attachments: Do error checking... soft fail - set the error and pass on the request. if ($data['attachments'] && is_array($data['attachments'])) { foreach ($data['attachments'] as &$file) { if ($file['encoding'] && !strcasecmp($file['encoding'], 'base64')) { if (!($file['data'] = base64_decode($file['data'], true))) { $file['error'] = sprintf(__('%s: Poorly encoded base64 data'), Format::htmlchars($file['name'])); } } // Validate and save immediately try { $file['id'] = $fileField->uploadAttachment($file); } catch (FileUploadError $ex) { $file['error'] = $file['name'] . ': ' . $ex->getMessage(); } } unset($file); } return true; }
} ?> </select> <span class='error'> <?php echo $errors['assignId']; ?></span> </td> </tr> <?php } ?> </tbody> <tbody id="dynamic-form"> <?php if ($form) { include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php'); } ?> </tbody> <tbody> <?php $tform = TicketForm::getInstance()->getForm($_POST); if ($_POST) $tform->isValid(); $tform->render(true); ?> </tbody> <tbody> <?php //is the user allowed to post replies?? if($thisstaff->canPostReply()) { ?> <tr> <th colspan="2"> <em><strong>Response</strong>: Optional response to the above issue.</em> </th> </tr> <tr> <td colspan=2>
$name = $f->get('name') ? $f->get('name') : 'field_' . $f->get('id'); $ids = $f->hasIdValue(); $fields = sprintf('`%s`=', $name) . db_input($answer->get('value')); if ($f->hasIdValue()) { $fields .= sprintf(',`%s_id`=', $name) . db_input($answer->getIdValue()); } $sql = 'INSERT INTO `' . TABLE_PREFIX . 'ticket__cdata` SET ' . $fields . ', `ticket_id`=' . db_input($answer->getEntry()->get('object_id')) . ' ON DUPLICATE KEY UPDATE ' . $fields; if (!db_query($sql) || !db_affected_rows()) { return self::dropDynamicDataView(); } } } // Add fields from the standard ticket form to the ticket filterable fields Filter::addSupportedMatches('Ticket Data', function () { $matches = array(); foreach (TicketForm::getInstance()->getFields() as $f) { if (!$f->hasData()) { continue; } $matches['field.' . $f->get('id')] = 'Ticket / ' . $f->getLabel(); if (($fi = $f->getImpl()) instanceof SelectionField) { foreach ($fi->getList()->getProperties() as $p) { $matches['field.' . $f->get('id') . '.' . $p->get('id')] = 'Ticket / ' . $f->getLabel() . ' / ' . $p->getLabel(); } } } return $matches; }, 30); // Manage materialized view on custom data updates Signal::connect('model.created', array('TicketForm', 'updateDynamicDataView'), 'DynamicFormEntryAnswer'); Signal::connect('model.updated', array('TicketForm', 'updateDynamicDataView'), 'DynamicFormEntryAnswer');
<?php if(($users=Staff::getStaffMembers())) { foreach($users as $id => $name) echo sprintf('<option value="%d">%s</option>', $id, $name); } ?> </select> </fieldset> <fieldset class="date_range"> <label><?php echo __('Date Range').' — '.__('Create Date');?>:</label> <input class="dp" type="input" size="20" name="startDate"> <span class="between"><?php echo __('TO');?></span> <input class="dp" type="input" size="20" name="endDate"> </fieldset> <?php $tform = TicketForm::objects()->one(); echo $tform->getForm()->getMedia(); foreach ($tform->getInstance()->getFields() as $f) { if (!$f->hasData()) continue; elseif (!$f->getImpl()->hasSpecialSearch()) continue; ?><fieldset class="span6"> <label><?php echo $f->getLabel(); ?>:</label><div><?php $f->render('search'); ?></div> </fieldset> <?php } ?> <hr/> <div id="result-count" class="clear"></div> <p> <span class="buttons pull-right">
define('SOURCE','Web'); //Ticket source. $ticket = null; $errors=array(); if ($_POST) { $vars = $_POST; $vars['deptId']=$vars['emailId']=0; //Just Making sure we don't accept crap...only topicId is expected. if ($thisclient) { $vars['uid']=$thisclient->getId(); } elseif($cfg->isCaptchaEnabled()) { if(!$_POST['captcha']) $errors['captcha']=__('Enter text shown on the image'); elseif(strcmp($_SESSION['captcha'], md5(strtoupper($_POST['captcha'])))) $errors['captcha']=__('Invalid - try again!'); } $tform = TicketForm::objects()->one()->getForm($vars); $messageField = $tform->getField('message'); $attachments = $messageField->getWidget()->getAttachments(); if (!$errors && $messageField->isAttachmentsEnabled()) $vars['cannedattachments'] = $attachments->getClean(); // Drop the draft.. If there are validation errors, the content // submitted will be displayed back to the user Draft::deleteForNamespace('ticket.client.'.substr(session_id(), -12)); //Ticket::create...checks for errors.. if(($ticket=Ticket::create($vars, $errors, SOURCE))){ $msg=__('Support ticket request created'); // Drop session-backed form data unset($_SESSION[':form-data']); //Logged in...simply view the newly created ticket. if($thisclient && $thisclient->isValid()) {
function _search($req) { global $thisstaff, $cfg; $result = array(); $select = 'SELECT ticket.ticket_id'; $from = ' FROM ' . TICKET_TABLE . ' ticket '; //Access control. $where = ' WHERE ( (ticket.staff_id=' . db_input($thisstaff->getId()) . ' AND ticket.status="open" )'; if (($teams = $thisstaff->getTeams()) && count(array_filter($teams))) { $where .= ' OR (ticket.team_id IN (' . implode(',', db_input(array_filter($teams))) . ' ) AND ticket.status="open")'; } if (!$thisstaff->showAssignedOnly() && ($depts = $thisstaff->getDepts())) { $where .= ' OR ticket.dept_id IN (' . implode(',', db_input($depts)) . ')'; } $where .= ' ) '; //Department if ($req['deptId']) { $where .= ' AND ticket.dept_id=' . db_input($req['deptId']); } //Help topic if ($req['topicId']) { $where .= ' AND ticket.topic_id=' . db_input($req['topicId']); } //Status switch (strtolower($req['status'])) { case 'open': $where .= ' AND ticket.status="open" '; break; case 'answered': $where .= ' AND ticket.status="open" AND ticket.isanswered=1 '; break; case 'overdue': $where .= ' AND ticket.status="open" AND ticket.isoverdue=1 '; break; case 'closed': $where .= ' AND ticket.status="closed" '; break; } //Assignee if (isset($req['assignee']) && strcasecmp($req['status'], 'closed')) { $id = preg_replace("/[^0-9]/", "", $req['assignee']); $assignee = $req['assignee']; $where .= ' AND ( ( ticket.status="open" '; if ($assignee[0] == 't') { $where .= ' AND ticket.team_id=' . db_input($id); } elseif ($assignee[0] == 's') { $where .= ' AND ticket.staff_id=' . db_input($id); } elseif (is_numeric($id)) { $where .= ' AND ticket.staff_id=' . db_input($id); } $where .= ')'; if ($req['staffId'] && !$req['status']) { //Assigned TO + Closed By $where .= ' OR (ticket.staff_id=' . db_input($req['staffId']) . ' AND ticket.status="closed") '; } elseif (isset($req['staffId'])) { // closed by any $where .= ' OR ticket.status="closed" '; } $where .= ' ) '; } elseif ($req['staffId']) { $where .= ' AND (ticket.staff_id=' . db_input($req['staffId']) . ' AND ticket.status="closed") '; } //dates $startTime = $req['startDate'] && strlen($req['startDate']) >= 8 ? strtotime($req['startDate']) : 0; $endTime = $req['endDate'] && strlen($req['endDate']) >= 8 ? strtotime($req['endDate']) : 0; if ($startTime && $startTime > time() or $startTime > $endTime && $endTime > 0) { $startTime = $endTime = 0; } if ($startTime) { $where .= ' AND ticket.created>=FROM_UNIXTIME(' . $startTime . ')'; } if ($endTime) { $where .= ' AND ticket.created<=FROM_UNIXTIME(' . $endTime . ')'; } //Query $joins = array(); if ($req['query']) { $queryterm = db_real_escape($req['query'], false); // Setup sets of joins and queries $joins[] = array('from' => 'LEFT JOIN ' . TICKET_THREAD_TABLE . ' thread ON (ticket.ticket_id=thread.ticket_id )', 'where' => "thread.title LIKE '%{$queryterm}%' OR thread.body LIKE '%{$queryterm}%'"); $joins[] = array('from' => 'LEFT JOIN ' . FORM_ENTRY_TABLE . ' tentry ON (tentry.object_id = ticket.ticket_id AND tentry.object_type="T") LEFT JOIN ' . FORM_ANSWER_TABLE . ' tans ON (tans.entry_id = tentry.id AND tans.value_id IS NULL)', 'where' => "tans.value LIKE '%{$queryterm}%'"); $joins[] = array('from' => 'LEFT JOIN ' . FORM_ENTRY_TABLE . ' uentry ON (uentry.object_id = ticket.user_id AND uentry.object_type="U") LEFT JOIN ' . FORM_ANSWER_TABLE . ' uans ON (uans.entry_id = uentry.id AND uans.value_id IS NULL) LEFT JOIN ' . USER_TABLE . ' user ON (ticket.user_id = user.id) LEFT JOIN ' . USER_EMAIL_TABLE . ' uemail ON (user.id = uemail.user_id)', 'where' => "uemail.address LIKE '%{$queryterm}%' OR user.name LIKE '%{$queryterm}%' OR uans.value LIKE '%{$queryterm}%'"); } // Dynamic fields $cdata_search = false; foreach (TicketForm::getInstance()->getFields() as $f) { if (isset($req[$f->getFormName()]) && ($val = $req[$f->getFormName()])) { $name = $f->get('name') ? $f->get('name') : 'field_' . $f->get('id'); if ($f->getImpl()->hasIdValue() && is_numeric($val)) { $cwhere = "cdata.`{$name}_id` = " . db_input($val); } else { $cwhere = "cdata.`{$name}` LIKE '%" . db_real_escape($val) . "%'"; } $where .= ' AND (' . $cwhere . ')'; $cdata_search = true; } } if ($cdata_search) { $from .= 'LEFT JOIN ' . TABLE_PREFIX . 'ticket__cdata ' . " cdata ON (cdata.ticket_id = ticket.ticket_id)"; } $sections = array(); foreach ($joins as $j) { $sections[] = "{$select} {$from} {$j['from']} {$where} AND ({$j['where']})"; } if (!$joins) { $sections[] = "{$select} {$from} {$where}"; } $sql = implode(' union ', $sections); if (!($res = db_query($sql))) { return TicketForm::dropDynamicDataView(); } $tickets = array(); while ($row = db_fetch_row($res)) { $tickets[] = $row[0]; } return $tickets; }
echo $thisclient->getName(); ?> </td></tr>--> <?php } ?> </tbody> <tbody id="dynamic-form"> <?php if ($form) { include CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php'; } ?> </tbody> <tbody id="fm"><?php $tform = TicketForm::getInstance(); if ($_POST) { $tform->isValidForClient(); } $tform->render(false); ?> </tbody> <tbody> <?php if ($cfg && $cfg->isCaptchaEnabled() && (!$thisclient || !$thisclient->isValid())) { if ($_POST && $errors && !$errors['captcha']) { $errors['captcha'] = __('Please re-enter the text again'); } ?> <tr class="captchaRow"> <td class="required"><?php
static function open($vars, &$errors) { global $thisstaff, $cfg; if (!$thisstaff || !$thisstaff->canCreateTickets()) { return false; } if ($vars['source'] && !in_array(strtolower($vars['source']), array('email', 'phone', 'other'))) { $errors['source'] = sprintf(__('Invalid source given - %s'), Format::htmlchars($vars['source'])); } if (!$vars['uid']) { //Special validation required here if (!$vars['email'] || !Validator::is_email($vars['email'])) { $errors['email'] = __('Valid email address is required'); } if (!$vars['name']) { $errors['name'] = __('Name is required'); } } if (!$thisstaff->canAssignTickets()) { unset($vars['assignId']); } $create_vars = $vars; $tform = TicketForm::objects()->one()->getForm($create_vars); $create_vars['cannedattachments'] = $tform->getField('message')->getWidget()->getAttachments()->getClean(); if (!($ticket = Ticket::create($create_vars, $errors, 'staff', false))) { return false; } $vars['msgId'] = $ticket->getLastMsgId(); // post response - if any $response = null; if ($vars['response'] && $thisstaff->canPostReply()) { $vars['response'] = $ticket->replaceVars($vars['response']); // $vars['cannedatachments'] contains the attachments placed on // the response form. $response = $ticket->postReply($vars, $errors, false); } // Not assigned...save optional note if any if (!$vars['assignId'] && $vars['note']) { if (!$cfg->isHtmlThreadEnabled()) { $vars['note'] = new TextThreadBody($vars['note']); } $ticket->logNote(_S('New Ticket'), $vars['note'], $thisstaff, false); } else { // Not assignment and no internal note - log activity $ticket->logActivity(_S('New Ticket by Agent'), sprintf(_S('Ticket created by agent - %s'), $thisstaff->getName())); } $ticket->reload(); if (!$cfg->notifyONNewStaffTicket() || !isset($vars['alertuser']) || !($dept = $ticket->getDept())) { return $ticket; } //No alerts. //Send Notice to user --- if requested AND enabled!! if (($tpl = $dept->getTemplate()) && ($msg = $tpl->getNewTicketNoticeMsgTemplate()) && ($email = $dept->getEmail())) { $message = (string) $ticket->getLastMessage(); if ($response) { $message .= $cfg->isHtmlThreadEnabled() ? "<br><br>" : "\n\n"; $message .= $response->getBody(); } if ($vars['signature'] == 'mine') { $signature = $thisstaff->getSignature(); } elseif ($vars['signature'] == 'dept' && $dept && $dept->isPublic()) { $signature = $dept->getSignature(); } else { $signature = ''; } $attachments = $cfg->emailAttachments() && $response ? $response->getAttachments() : array(); $msg = $ticket->replaceVars($msg->asArray(), array('message' => $message, 'signature' => $signature, 'response' => $response ? $response->getBody() : '', 'recipient' => $ticket->getOwner(), 'staff' => $thisstaff)); $references = $ticket->getLastMessage()->getEmailMessageId(); if (isset($response)) { $references = array($response->getEmailMessageId(), $references); } $options = array('references' => $references, 'thread' => $ticket->getLastMessage()); $email->send($ticket->getOwner(), $msg['subj'], $msg['body'], $attachments, $options); } return $ticket; }
static function create($vars, &$errors, $origin, $autorespond = true, $alertstaff = true) { global $ost, $cfg, $thisclient, $_FILES; // Don't enforce form validation for email $field_filter = function ($type) use($origin) { return function ($f) use($origin, $type) { // Ultimately, only offer validation errors for web for // non-internal fields. For email, no validation can be // performed. For other origins, validate as usual switch (strtolower($origin)) { case 'email': return false; case 'staff': // Required 'Contact Information' fields aren't required // when staff open tickets return $type != 'user' || in_array($f->get('name'), array('name', 'email')); case 'web': return !$f->get('private'); default: return true; } }; }; $reject_ticket = function ($message) use(&$errors) { global $ost; $errors = array('errno' => 403, 'err' => 'This help desk is for use by authorized users only'); $ost->logWarning('Ticket Denied', $message, false); return 0; }; // Create and verify the dynamic form entry for the new ticket $form = TicketForm::getNewInstance(); // If submitting via email, ensure we have a subject and such foreach ($form->getFields() as $field) { $fname = $field->get('name'); if ($fname && isset($vars[$fname]) && !$field->value) { $field->value = $field->parse($vars[$fname]); } } if (!$form->isValid($field_filter('ticket'))) { $errors += $form->errors(); } // Unpack dynamic variables into $vars for filter application $vars += $form->getFilterData(); // Unpack the basic user information if ($vars['uid'] && ($user = User::lookup($vars['uid']))) { $vars['email'] = $user->getEmail(); $vars['name'] = $user->getName(); // Add in user and organization data for filtering $vars += $user->getFilterData(); if ($org = $user->getOrganization()) { $vars += $org->getFilterData(); } } else { $interesting = array('name', 'email'); $user_form = UserForm::getUserForm()->getForm($vars); // Add all the user-entered info for filtering foreach ($user_form->getFields() as $f) { $vars['field.' . $f->get('id')] = $f->toString($f->getClean()); if (in_array($f->get('name'), $interesting)) { $vars[$f->get('name')] = $vars['field.' . $f->get('id')]; } } // Add in organization data if one exists for this email domain list($mailbox, $domain) = explode('@', $vars['email'], 2); if ($org = Organization::forDomain($domain)) { $vars += $org->getFilterData(); } } //Check for 403 if ($vars['email'] && Validator::is_email($vars['email'])) { //Make sure the email address is not banned if (TicketFilter::isBanned($vars['email'])) { return $reject_ticket('Banned email - ' . $vars['email']); } //Make sure the open ticket limit hasn't been reached. (LOOP CONTROL) if ($cfg->getMaxOpenTickets() > 0 && strcasecmp($origin, 'staff') && ($_user = TicketUser::lookupByEmail($vars['email'])) && ($openTickets = $_user->getNumOpenTickets()) && $openTickets >= $cfg->getMaxOpenTickets()) { $errors = array('err' => "You've reached the maximum open tickets allowed."); $ost->logWarning('Ticket denied -' . $vars['email'], sprintf('Max open tickets (%d) reached for %s ', $cfg->getMaxOpenTickets(), $vars['email']), false); return 0; } } //Init ticket filters... $ticket_filter = new TicketFilter($origin, $vars); // Make sure email contents should not be rejected if ($ticket_filter && ($filter = $ticket_filter->shouldReject())) { return $reject_ticket(sprintf('Ticket rejected ( %s) by filter "%s"', $vars['email'], $filter->getName())); } if ($vars['topicId'] && ($topic = Topic::lookup($vars['topicId']))) { if ($topic_form = $topic->getForm()) { $TF = $topic_form->getForm($vars); $topic_form = $topic_form->instanciate(); $topic_form->setSource($vars); if (!$TF->isValid($field_filter('topic'))) { $errors = array_merge($errors, $TF->errors()); } } } $id = 0; $fields = array(); $fields['message'] = array('type' => '*', 'required' => 1, 'error' => 'Message required'); switch (strtolower($origin)) { case 'web': $fields['topicId'] = array('type' => 'int', 'required' => 1, 'error' => 'Select help topic'); break; case 'staff': $fields['deptId'] = array('type' => 'int', 'required' => 0, 'error' => 'Dept. required'); $fields['topicId'] = array('type' => 'int', 'required' => 1, 'error' => 'Topic required'); $fields['duedate'] = array('type' => 'date', 'required' => 0, 'error' => 'Invalid date - must be MM/DD/YY'); case 'api': $fields['source'] = array('type' => 'string', 'required' => 1, 'error' => 'Indicate source'); break; case 'email': $fields['emailId'] = array('type' => 'int', 'required' => 1, 'error' => 'Email unknown'); break; default: # TODO: Return error message $errors['err'] = $errors['origin'] = 'Invalid origin given'; } if (!Validator::process($fields, $vars, $errors) && !$errors['err']) { $errors['err'] = 'Missing or invalid data - check the errors and try again'; } if ($vars['topicId'] && !$topic) { $errors['topicId'] = 'Invalid help topic selected'; } //Make sure the due date is valid if ($vars['duedate']) { if (!$vars['time'] || strpos($vars['time'], ':') === false) { $errors['time'] = 'Select time'; } elseif (strtotime($vars['duedate'] . ' ' . $vars['time']) === false) { $errors['duedate'] = 'Invalid due date'; } elseif (strtotime($vars['duedate'] . ' ' . $vars['time']) <= time()) { $errors['duedate'] = 'Due date must be in the future'; } } if (!$errors) { # Perform ticket filter actions on the new ticket arguments if ($ticket_filter) { $ticket_filter->apply($vars); } // Allow vars to be changed in ticket filter and applied to the user // account created or detected if (!$user && $vars['email']) { $user = User::lookupByEmail($vars['email']); } if (!$user) { // Reject emails if not from registered clients (if // configured) if (strcasecmp($origin, 'email') === 0 && !$cfg->acceptUnregisteredEmail()) { list($mailbox, $domain) = explode('@', $vars['email'], 2); // Users not yet created but linked to an organization // are still acceptable if (!Organization::forDomain($domain)) { return $reject_ticket(sprintf('Ticket rejected (%s) (unregistered client)', $vars['email'])); } } $user_form = UserForm::getUserForm()->getForm($vars); if (!$user_form->isValid($field_filter('user')) || !($user = User::fromVars($user_form->getClean()))) { $errors['user'] = '******'; } } } // Any error above is fatal. if ($errors) { return 0; } # Some things will need to be unpacked back into the scope of this # function if (isset($vars['autorespond'])) { $autorespond = $vars['autorespond']; } # Apply filter-specific priority if ($vars['priorityId']) { $form->setAnswer('priority', null, $vars['priorityId']); } // If the filter specifies a help topic which has a form associated, // and there was previously either no help topic set or the help // topic did not have a form, there's no need to add it now as (1) // validation is closed, (2) there may be a form already associated // and filled out from the original help topic, and (3) staff // members can always add more forms now // OK...just do it. $deptId = $vars['deptId']; //pre-selected Dept if any. $source = ucfirst($vars['source']); // Apply email settings for emailed tickets. Email settings should // trump help topic settins if the email has an associated help // topic if ($vars['emailId'] && ($email = Email::lookup($vars['emailId']))) { $deptId = $deptId ?: $email->getDeptId(); $priority = $form->getAnswer('priority'); if (!$priority || !$priority->getIdValue()) { $form->setAnswer('priority', null, $email->getPriorityId()); } if ($autorespond) { $autorespond = $email->autoRespond(); } if (!isset($topic) && ($T = $email->getTopic()) && $T->isActive()) { $topic = $T; } $email = null; $source = 'Email'; } if (!isset($topic)) { // This may return NULL, no big deal $topic = $cfg->getDefaultTopic(); } // Intenal mapping magic...see if we need to override anything if (isset($topic)) { $deptId = $deptId ?: $topic->getDeptId(); $priority = $form->getAnswer('priority'); if (!$priority || !$priority->getIdValue()) { $form->setAnswer('priority', null, $topic->getPriorityId()); } if ($autorespond) { $autorespond = $topic->autoRespond(); } //Auto assignment. if (!isset($vars['staffId']) && $topic->getStaffId()) { $vars['staffId'] = $topic->getStaffId(); } elseif (!isset($vars['teamId']) && $topic->getTeamId()) { $vars['teamId'] = $topic->getTeamId(); } //set default sla. if (isset($vars['slaId'])) { $vars['slaId'] = $vars['slaId'] ?: $cfg->getDefaultSLAId(); } elseif ($topic && $topic->getSLAId()) { $vars['slaId'] = $topic->getSLAId(); } } // Auto assignment to organization account manager if (($org = $user->getOrganization()) && $org->autoAssignAccountManager() && ($code = $org->getAccountManagerId())) { if (!isset($vars['staffId']) && $code[0] == 's') { $vars['staffId'] = substr($code, 1); } elseif (!isset($vars['teamId']) && $code[0] == 't') { $vars['teamId'] = substr($code, 1); } } // Last minute checks $priority = $form->getAnswer('priority'); if (!$priority || !$priority->getIdValue()) { $form->setAnswer('priority', null, $cfg->getDefaultPriorityId()); } $deptId = $deptId ?: $cfg->getDefaultDeptId(); $topicId = isset($topic) ? $topic->getId() : 0; $ipaddress = $vars['ip'] ?: $_SERVER['REMOTE_ADDR']; $source = $source ?: 'Web'; //We are ready son...hold on to the rails. $number = Ticket::genRandTicketNumber(); $sql = 'INSERT INTO ' . TICKET_TABLE . ' SET created=NOW() ' . ' ,lastmessage= NOW()' . ' ,user_id=' . db_input($user->getId()) . ' ,`number`=' . db_input($number) . ' ,dept_id=' . db_input($deptId) . ' ,topic_id=' . db_input($topicId) . ' ,ip_address=' . db_input($ipaddress) . ' ,source=' . db_input($source); if (isset($vars['emailId']) && $vars['emailId']) { $sql .= ', email_id=' . db_input($vars['emailId']); } //Make sure the origin is staff - avoid firebug hack! if ($vars['duedate'] && !strcasecmp($origin, 'staff')) { $sql .= ' ,duedate=' . db_input(date('Y-m-d G:i', Misc::dbtime($vars['duedate'] . ' ' . $vars['time']))); } if (!db_query($sql) || !($id = db_insert_id()) || !($ticket = Ticket::lookup($id))) { return null; } /* -------------------- POST CREATE ------------------------ */ if (!$cfg->useRandomIds()) { //Sequential ticket number support really..really suck arse. //To make things really easy we are going to use autoincrement ticket_id. db_query('UPDATE ' . TICKET_TABLE . ' SET `number`=' . db_input($id) . ' WHERE ticket_id=' . $id . ' LIMIT 1'); //TODO: RETHING what happens if this fails?? [At the moment on failure random ID is used...making stuff usable] } // Save the (common) dynamic form $form->setTicketId($id); $form->save(); // Save the form data from the help-topic form, if any if ($topic_form) { $topic_form->setTicketId($id); $topic_form->save(); } $ticket->loadDynamicData(); $dept = $ticket->getDept(); // Add organizational collaborators if ($org && $org->autoAddCollabs()) { $pris = $org->autoAddPrimaryContactsAsCollabs(); $members = $org->autoAddMembersAsCollabs(); $settings = array('isactive' => true); $collabs = array(); foreach ($org->allMembers() as $u) { if ($members || $pris && $u->isPrimaryContact()) { if ($c = $ticket->addCollaborator($u, $settings, $errors)) { $collabs[] = (string) $c; } } } //TODO: Can collaborators add others? if ($collabs) { //TODO: Change EndUser to name of user. $ticket->logNote(sprintf('Collaborators for %s organization added', $org->getName()), implode("<br>", $collabs), $org->getName(), false); } } //post the message. unset($vars['cannedattachments']); //Ticket::open() might have it set as part of open & respond. $vars['title'] = $vars['subject']; //Use the initial subject as title of the post. $vars['userId'] = $ticket->getUserId(); $message = $ticket->postMessage($vars, $origin, false); // Configure service-level-agreement for this ticket $ticket->selectSLAId($vars['slaId']); // Assign ticket to staff or team (new ticket by staff) if ($vars['assignId']) { $ticket->assign($vars['assignId'], $vars['note']); } else { // Auto assign staff or team - auto assignment based on filter // rules. Both team and staff can be assigned if ($vars['staffId']) { $ticket->assignToStaff($vars['staffId'], 'Auto Assignment'); } if ($vars['teamId']) { $ticket->assignToTeam($vars['teamId'], 'Auto Assignment'); } } /********** double check auto-response ************/ //Override auto responder if the FROM email is one of the internal emails...loop control. if ($autorespond && Email::getIdByEmail($ticket->getEmail())) { $autorespond = false; } # Messages that are clearly auto-responses from email systems should # not have a return 'ping' message if (isset($vars['flags']) && $vars['flags']['bounce']) { $autorespond = false; } if ($autorespond && $message->isAutoReply()) { $autorespond = false; } //post canned auto-response IF any (disables new ticket auto-response). if ($vars['cannedResponseId'] && $ticket->postCannedReply($vars['cannedResponseId'], $message->getId(), $autorespond)) { $ticket->markUnAnswered(); //Leave the ticket as unanswred. $autorespond = false; } //Check department's auto response settings // XXX: Dept. setting doesn't affect canned responses. if ($autorespond && $dept && !$dept->autoRespONNewTicket()) { $autorespond = false; } //Don't send alerts to staff when the message is a bounce // this is necessary to avoid possible loop (especially on new ticket) if ($alertstaff && $message->isBounce()) { $alertstaff = false; } /***** See if we need to send some alerts ****/ $ticket->onNewTicket($message, $autorespond, $alertstaff); /************ check if the user JUST reached the max. open tickets limit **********/ if ($cfg->getMaxOpenTickets() > 0 && ($user = $ticket->getOwner()) && $user->getNumOpenTickets() == $cfg->getMaxOpenTickets()) { $ticket->onOpenLimit($autorespond && strcasecmp($origin, 'staff')); } /* Start tracking ticket lifecycle events */ $ticket->logEvent('created'); /* Phew! ... time for tea (KETEPA) */ return $ticket; }
function createTicketByWebService($xml) { global $logFilePath; try { if (!empty($xml)) { $nodes = $xml->xpath('/contacts/contact'); } else { logErrors("The xml file can not be loaded "); } for ($i = 0; $i < count($nodes); $i++) { // echo json_encode($nodes[$i]); $data = array(); // $data['recipients'] = array(); $data['subject'] = removeLineBreaker($nodes[$i]->title); if (empty(removeLineBreaker($nodes[$i]->title))) { if (!empty(removeLineBreaker($nodes[$i]->crmsubject2_text))) { $data['subject'] = removeLineBreaker($nodes[$i]->crmsubject2_text); } else { $data['subject'] = "no title"; } } $data['header'] = ""; // $data['mid'] = 1; $data['source'] = "Web"; $data['topicId'] = 2; $data['priorityId'] = 2; $data['crm_contact_id'] = $nodes[$i]->attributes()->id; // $data['flags'] = new ArrayObject(); $data['email'] = trim(removeLineBreaker($nodes[$i]->email)); if (empty($data['email'])) { $data['email'] = "*****@*****.**"; } $data['phone'] = removeLineBreaker($nodes[$i]->phone); if (empty($data['phone'])) { $data['phone'] = ""; } $data['name'] = trim(removeLineBreaker($nodes[$i]->name)); if (empty($data['name'])) { $data['name'] = "Anonymous User"; } $data['orderNumber'] = trim(removeLineBreaker($nodes[$i]->ordernumber)); $data['ordernumber'] = trim(removeLineBreaker($nodes[$i]->ordernumber)); $data['filenumber'] = trim(removeLineBreaker($nodes[$i]->filenumber)); $data['cvr'] = trim(removeLineBreaker($nodes[$i]->cvr)); $data['CVR'] = trim(removeLineBreaker($nodes[$i]->cvr)); $data['message'] = removeLineBreaker($nodes[$i]->content); $data['companyName'] = removeLineBreaker($nodes[$i]->companyname); $data['company'] = removeLineBreaker($nodes[$i]->companyname); $data['business_form_id'] = removeLineBreaker($nodes[$i]->business_form_id); $data['activityCode'] = removeLineBreaker($nodes[$i]->activitycode); $data['activityDescription'] = removeLineBreaker($nodes[$i]->activitydescription); $data['useragent'] = removeLineBreaker($nodes[$i]->useragent); $crmsubject1_id = trim(removeLineBreaker($nodes[$i]->crmsubject_id)); if (is_numeric($crmsubject1_id)) { $data['CRM_filter_subject1'] = removeLineBreaker($nodes[$i]->crmsubject_text); $data['crmsubject1_id'] = intval($crmsubject1_id); $data['crmsubject1_text'] = removeLineBreaker($nodes[$i]->crmsubject_text); } else { die("crmsubject1_id is not numeric"); } $crmsubject2_id = trim(removeLineBreaker($nodes[$i]->crmsubject2_id)); if (is_numeric($crmsubject2_id)) { $data['CRM_filter_subject2'] = removeLineBreaker($nodes[$i]->crmsubject2_text); $data['crmsubject2_id'] = intval($crmsubject2_id); $data['crmsubject2_text'] = removeLineBreaker($nodes[$i]->crmsubject2_text); } else { die("crmsubject2_id is not numeric"); } // $data['flags']['bounce'] = true; $user = null; $acct = null; if (!$user && $data['email']) { $user = User::lookupByEmail($data['email']); } if (!$user) { $user_form = UserForm::getUserForm()->getForm($data); if (!($user = User::fromVars($user_form->getClean()))) { echo 'Unable to register account.'; } if (!($acct = ClientAccount::createForUser($user))) { echo 'Internal error. Unable to create new account'; } } $fileContent = $nodes[$i]->files->file; $data['fileContent'] = $fileContent; $tform = TicketForm::objects()->one()->getForm(); $messageField = $tform->getField('message'); $fileField = $messageField->getWidget()->getAttachments(); for ($j = 0; $j < count($fileContent); $j++) { $fileId = $fileContent[$j]->attributes()->id; $file['name'] = $fileContent[$j]->name; $file['type'] = $fileContent[$j]->mime; $file['encoding'] = 'base64'; // $file['cid'] = false; $url = "https://w2l.dk" . $fileContent[$j]->url; // logErrors("A test"); // $url = $fileContent[$j]->url; // $file['data'] = base64_encode(file_get_contents($url)); if ($file['data'] = getFileContentsSSL($url)) { $timestamp = date("Y-m-d_H:i:s"); // if(!file_put_contents(CLIENTINC_DIR.'erstFile/'.$timestamp.$file['name'], $file['data'])) // logErrors("not able to store the file"); try { $storeCRMFile = "/var/www/html/erstFile/" . $timestamp . $file['name']; echo $storeCRMFile; file_put_contents("/var/www/html/erstFile/" . $timestamp . $file['name'], $file['data']); } catch (Exception $e) { logErrors('Caught exception: ', $e->getMessage(), "\n"); } } else { logErrors("The file url is not valid"); } // try { // $file['id'] = $fileField->uploadAttachment($file); // } // catch (FileUploadError $ex) { // $file['error'] = $file['name'] . ': ' . $ex->getMessage(); // echo $file['error']; // } $data['attachments'][] = $file; // echo $file['data']; // echo "<br/>"; } // echo "22222"; // echo json_encode($data); if (Ticket::lookupForContactId($data['crm_contact_id'])) { $api = new TicketApiController(); $api->createTicket($data); echo "ticket has been generated successfully <br/>"; if (DELETE_ERST_SERVICE_QUEUE) { deleteContactsFromQueue($data['crm_contact_id']); } else { logErrors("please go to include/ost-config to make the DELETE_ERST_SERVICE_QUEUE to true"); } } else { logErrors("ticket with id " . $data['crm_contact_id'] . " has already exists"); } } } catch (Exception $e) { echo 'Caught exception: ', $e->getMessage(), "\n"; } }
<?php $select = 'SELECT ticket.ticket_id,ticket.`number`,ticket.dept_id,ticket.staff_id,ticket.team_id, ticket.user_id ' . ' ,dept.dept_name,status.name as status,ticket.source,ticket.isoverdue,ticket.isanswered,ticket.created ' . ' ,CAST(GREATEST(IFNULL(ticket.lastmessage, 0), IFNULL(ticket.reopened, 0), ticket.created) as datetime) as effective_date ' . ' ,CONCAT_WS(" ", staff.firstname, staff.lastname) as staff, team.name as team ' . ' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned ' . ' ,IF(ptopic.topic_pid IS NULL, topic.topic, CONCAT_WS(" / ", ptopic.topic, topic.topic)) as helptopic ' . ' ,cdata.priority as priority_id, cdata.subject, user.name, email.address as email'; $from = ' FROM ' . TICKET_TABLE . ' ticket ' . ' LEFT JOIN ' . TICKET_STATUS_TABLE . ' status ON status.id = ticket.status_id ' . ' LEFT JOIN ' . USER_TABLE . ' user ON user.id = ticket.user_id ' . ' LEFT JOIN ' . USER_EMAIL_TABLE . ' email ON user.id = email.user_id ' . ' LEFT JOIN ' . USER_ACCOUNT_TABLE . ' account ON (ticket.user_id=account.user_id) ' . ' LEFT JOIN ' . DEPT_TABLE . ' dept ON ticket.dept_id=dept.dept_id ' . ' LEFT JOIN ' . STAFF_TABLE . ' staff ON (ticket.staff_id=staff.staff_id) ' . ' LEFT JOIN ' . TEAM_TABLE . ' team ON (ticket.team_id=team.team_id) ' . ' LEFT JOIN ' . TOPIC_TABLE . ' topic ON (ticket.topic_id=topic.topic_id) ' . ' LEFT JOIN ' . TOPIC_TABLE . ' ptopic ON (ptopic.topic_id=topic.topic_pid) ' . ' LEFT JOIN ' . TABLE_PREFIX . 'ticket__cdata cdata ON (cdata.ticket_id = ticket.ticket_id) ' . ' LEFT JOIN ' . PRIORITY_TABLE . ' pri ON (pri.priority_id = cdata.priority)'; if ($user) { $where = 'WHERE ticket.user_id = ' . db_input($user->getId()); } elseif ($org) { $where = 'WHERE user.org_id = ' . db_input($org->getId()); } TicketForm::ensureDynamicDataView(); $query = "{$select} {$from} {$where} ORDER BY ticket.created DESC"; // Fetch the results $results = array(); $res = db_query($query); while ($row = db_fetch_array($res)) { $results[$row['ticket_id']] = $row; } if ($results) { $counts_sql = 'SELECT ticket.ticket_id, count(DISTINCT attach.attach_id) as attachments, count(DISTINCT thread.id) as thread_count, count(DISTINCT collab.id) as collaborators FROM ' . TICKET_TABLE . ' ticket LEFT JOIN ' . TICKET_ATTACHMENT_TABLE . ' attach ON (ticket.ticket_id=attach.ticket_id) ' . ' LEFT JOIN ' . TICKET_THREAD_TABLE . ' thread ON ( ticket.ticket_id=thread.ticket_id) ' . ' LEFT JOIN ' . TICKET_COLLABORATOR_TABLE . ' collab ON ( ticket.ticket_id=collab.ticket_id) ' . ' WHERE ticket.ticket_id IN (' . implode(',', db_input(array_keys($results))) . ') GROUP BY ticket.ticket_id'; $ids_res = db_query($counts_sql); while ($row = db_fetch_array($ids_res)) { $results[$row['ticket_id']] += $row; }
function _search($req) { global $thisstaff, $cfg, $ost; $result = array(); $criteria = array(); $select = 'SELECT ticket.ticket_id'; $from = ' FROM ' . TICKET_TABLE . ' ticket LEFT JOIN ' . TICKET_STATUS_TABLE . ' status ON (status.id = ticket.status_id) '; //Access control. $where = ' WHERE ( (ticket.staff_id=' . db_input($thisstaff->getId()) . ' AND status.state="open" )'; if (($teams = $thisstaff->getTeams()) && count(array_filter($teams))) { $where .= ' OR (ticket.team_id IN (' . implode(',', db_input(array_filter($teams))) . ' ) AND status.state="open" )'; } if (!$thisstaff->showAssignedOnly() && ($depts = $thisstaff->getDepts())) { $where .= ' OR ticket.dept_id IN (' . implode(',', db_input($depts)) . ')'; } $where .= ' ) '; //Department if ($req['deptId']) { $where .= ' AND ticket.dept_id=' . db_input($req['deptId']); $criteria['dept_id'] = $req['deptId']; } //Help topic if ($req['topicId']) { $where .= ' AND ticket.topic_id=' . db_input($req['topicId']); $criteria['topic_id'] = $req['topicId']; } // Status if ($req['statusId'] && ($status = TicketStatus::lookup($req['statusId']))) { $where .= sprintf(' AND status.id="%d" ', $status->getId()); $criteria['status_id'] = $status->getId(); } // Flags if ($req['flag']) { switch (strtolower($req['flag'])) { case 'answered': $where .= ' AND ticket.isanswered =1 '; $criteria['isanswered'] = 1; $criteria['state'] = 'open'; $where .= ' AND status.state="open" '; break; case 'overdue': $where .= ' AND ticket.isoverdue =1 '; $criteria['isoverdue'] = 1; $criteria['state'] = 'open'; $where .= ' AND status.state="open" '; break; } } //Assignee if ($req['assignee'] && strcasecmp($req['status'], 'closed')) { # assigned-to $id = preg_replace("/[^0-9]/", "", $req['assignee']); $assignee = $req['assignee']; $where .= ' AND ( ( status.state="open" '; if ($assignee[0] == 't') { $where .= ' AND ticket.team_id=' . db_input($id); $criteria['team_id'] = $id; } elseif ($assignee[0] == 's' || is_numeric($id)) { $where .= ' AND ticket.staff_id=' . db_input($id); $criteria['staff_id'] = $id; } $where .= ')'; if ($req['staffId'] && !$req['status']) { //Assigned TO + Closed By $where .= ' OR (ticket.staff_id=' . db_input($req['staffId']) . ' AND status.state IN("closed")) '; } elseif ($req['staffId']) { // closed by any $where .= ' OR status.state IN("closed") '; } $where .= ' ) '; } elseif ($req['staffId']) { # closed-by $where .= ' AND (ticket.staff_id=' . db_input($req['staffId']) . ' AND status.state IN("closed")) '; $criteria['state__in'] = array('closed'); $criteria['staff_id'] = $req['staffId']; } //dates $startTime = $req['startDate'] && strlen($req['startDate']) >= 8 ? strtotime($req['startDate']) : 0; $endTime = $req['endDate'] && strlen($req['endDate']) >= 8 ? strtotime($req['endDate']) : 0; if ($endTime) { // $endTime should be the last second of the day, not the first like $startTime $endTime += 60 * 60 * 24 - 1; } if ($startTime && $startTime > time() or $startTime > $endTime && $endTime > 0) { $startTime = $endTime = 0; } if ($startTime) { $where .= ' AND ticket.created>=FROM_UNIXTIME(' . $startTime . ')'; $criteria['created__gte'] = $startTime; } if ($endTime) { $where .= ' AND ticket.created<=FROM_UNIXTIME(' . $endTime . ')'; $criteria['created__lte'] = $startTime; } // Dynamic fields $cdata_search = false; foreach (TicketForm::getInstance()->getFields() as $f) { if (isset($req[$f->getFormName()]) && ($val = $req[$f->getFormName()])) { $name = $f->get('name') ? $f->get('name') : 'field_' . $f->get('id'); if (is_array($val)) { $cwhere = '(' . implode(' OR ', array_map(function ($k) use($name) { return sprintf('FIND_IN_SET(%s, `%s`)', db_input($k), $name); }, $val)) . ')'; $criteria["cdata.{$name}"] = $val; } else { $cwhere = "cdata.`{$name}` LIKE '%" . db_real_escape($val) . "%'"; $criteria["cdata.{$name}"] = $val; } $where .= ' AND (' . $cwhere . ')'; $cdata_search = true; } } if ($cdata_search) { $from .= 'LEFT JOIN ' . TABLE_PREFIX . 'ticket__cdata ' . " cdata ON (cdata.ticket_id = ticket.ticket_id)"; } //Query $joins = array(); if ($req['query']) { // Setup sets of joins and queries if ($s = $ost->searcher) { return $s->find($req['query'], $criteria, 'Ticket'); } } $sections = array(); foreach ($joins as $j) { $sections[] = "{$select} {$from} {$j['from']} {$where} AND ({$j['where']})"; } if (!$joins) { $sections[] = "{$select} {$from} {$where}"; } $sql = implode(' union ', $sections); if (!($res = db_query($sql))) { return TicketForm::dropDynamicDataView(); } $tickets = array(); while ($row = db_fetch_row($res)) { $tickets[] = $row[0]; } return $tickets; }
static function dumpTickets($sql, $how = 'csv') { // Add custom fields to the $sql statement $cdata = $fields = $select = array(); foreach (TicketForm::getInstance()->getFields() as $f) { // Ignore core fields if (in_array($f->get('name'), array('subject', 'priority'))) { continue; } elseif (!$f->hasData() || $f->isPresentationOnly()) { continue; } $name = $f->get('name') ? $f->get('name') : 'field_' . $f->get('id'); $key = '__field_' . $f->get('id'); $cdata[$key] = $f->get('label'); $fields[$key] = $f; $select[] = "cdata.`{$name}` AS __field_" . $f->get('id'); } //Inicio 13/04/2016 Se agrego el campo tiempo a cdata para mostrarlo en el archivo junto con el tiempo de duracion del ticket $cdata['tiempo'] = 'Tiempo de Respuesta'; $select[] = "'Tiempo de Respuesta' AS tiempo"; //Fin 13/04/2016 Se agrego el campo tiempo a cdata para mostrarlo en el archivo junto con el tiempo de duracion del ticket if ($select) { $sql = str_replace(' FROM ', ',' . implode(',', $select) . ' FROM ', $sql); } return self::dumpQuery($sql, array('number' => __('Ticket Number'), 'ticket_created' => __('Date'), 'subject' => __('Subject'), 'name' => __('From'), 'email' => __('From Email'), 'priority_desc' => __('Priority'), 'dept_name' => __('Department'), 'helptopic' => __('Help Topic'), 'source' => __('Source'), 'status' => __('Current Status'), 'effective_date' => __('Last Updated'), 'duedate' => __('Due Date'), 'isoverdue' => __('Overdue'), 'isanswered' => __('Answered'), 'assigned' => __('Assigned To'), 'staff' => __('Agent Assigned'), 'team' => __('Team Assigned'), 'thread_count' => __('Thread Count'), 'attachments' => __('Attachment Count')) + $cdata, $how, array('modify' => function (&$record, $keys) use($fields) { foreach ($fields as $k => $f) { if (($i = array_search($k, $keys)) !== false) { $record[$i] = $f->export($f->to_php($record[$i])); } } //Inicio 13/04/2016 Se llena la comlumna tiempo del archivo con la duracion de cada ticket $fecha1 = new DateTime($record[1]); if ($_REQUEST["status"] == "open" || $_REQUEST["status"] == "assigned") { $fecha2 = new DateTime(date("Y-m-d H:i:s")); } else { $fecha2 = new DateTime($record[10]); } $fecha = $fecha1->diff($fecha2); if ($fecha->y > 0) { $record[$i + 1] = $fecha->y . "A " . $fecha->m . "M " . $fecha->d . "d " . $fecha->h . "h " . $fecha->i . "m "; } else { if ($fecha->m > 0) { $record[$i + 1] = $fecha->m . "M " . $fecha->d . "d " . $fecha->h . "h " . $fecha->i . "m "; } else { if ($fecha->d > 0) { $record[$i + 1] = $fecha->d . "d " . $fecha->h . "h " . $fecha->i . "m "; } else { if ($fecha->h > 0) { $record[$i + 1] = $fecha->h . "h " . $fecha->i . "m "; } else { if ($fecha->i > 0) { $record[$i + 1] = $fecha->i . "m "; } else { $record[$i + 1] = '0m'; } } } } } return $record; //Inicio 13/04/2016 Se llena la comlumna tiempo del archivo con la duracion de cada ticket })); }
function createTicket($mid) { global $ost; if (!($mailinfo = $this->getHeaderInfo($mid))) { return false; } // TODO: If the content-type of the message is 'message/rfc822', // then this is a message with the forwarded message as the // attachment. Download the body and pass it along to the mail // parsing engine. $info = Mail_Parse::splitHeaders($mailinfo['header']); if (strtolower($info['Content-Type']) == 'message/rfc822') { if ($wrapped = $this->getPart($mid, 'message/rfc822')) { require_once INCLUDE_DIR . 'api.tickets.php'; // Simulate piping the contents into the system $api = new TicketApiController(); $parser = new EmailDataParser(); if ($data = $parser->parse($wrapped)) { return $api->processEmail($data); } } // If any of this fails, create the ticket as usual } //Is the email address banned? if ($mailinfo['email'] && TicketFilter::isBanned($mailinfo['email'])) { //We need to let admin know... $ost->logWarning(_S('Ticket denied'), sprintf(_S('Banned email — %s'), $mailinfo['email']), false); return true; //Report success (moved or delete) } // Parse MS TNEF emails if (($struct = imap_fetchstructure($this->mbox, $mid)) && ($attachments = $this->getAttachments($struct))) { foreach ($attachments as $i => $info) { if (0 === strcasecmp('application/ms-tnef', $info['type'])) { try { $data = $this->decode(imap_fetchbody($this->mbox, $mid, $info['index']), $info['encoding']); $tnef = new TnefStreamParser($data); $this->tnef = $tnef->getMessage(); // No longer considered an attachment unset($attachments[$i]); // There should only be one of these break; } catch (TnefException $ex) { // Noop -- winmail.dat remains an attachment } } } } $vars = $mailinfo; $vars['name'] = $mailinfo['name']; $vars['subject'] = $mailinfo['subject'] ?: '[No Subject]'; $vars['emailId'] = $mailinfo['emailId'] ?: $this->getEmailId(); $vars['to-email-id'] = $mailinfo['emailId'] ?: 0; $vars['flags'] = new ArrayObject(); if ($this->isBounceNotice($mid)) { // Fetch the original References and assign to 'references' if ($headers = $this->getOriginalMessageHeaders($mid)) { $vars['references'] = $headers['references']; $vars['in-reply-to'] = @$headers['in-reply-to'] ?: null; } // Fetch deliver status report $vars['message'] = $this->getDeliveryStatusMessage($mid) ?: $this->getBody($mid); $vars['thread-type'] = 'N'; $vars['flags']['bounce'] = true; } else { $vars['message'] = $this->getBody($mid); $vars['flags']['bounce'] = TicketFilter::isBounce($info); } //Missing FROM name - use email address. if (!$vars['name']) { list($vars['name']) = explode('@', $vars['email']); } if ($ost->getConfig()->useEmailPriority()) { $vars['priorityId'] = $this->getPriority($mid); } $ticket = null; $newticket = true; $errors = array(); $seen = false; // Use the settings on the thread entry on the ticket details // form to validate the attachments in the email $tform = TicketForm::objects()->one()->getForm(); $messageField = $tform->getField('message'); $fileField = $messageField->getWidget()->getAttachments(); // Fetch attachments if any. if ($messageField->isAttachmentsEnabled()) { // Include TNEF attachments in the attachments list if ($this->tnef) { foreach ($this->tnef->attachments as $at) { $attachments[] = array('cid' => @$at->AttachContentId ?: false, 'data' => $at, 'size' => @$at->DataSize ?: null, 'type' => @$at->AttachMimeTag ?: false, 'name' => $at->getName()); } } $vars['attachments'] = array(); foreach ($attachments as $a) { $file = array('name' => $a['name'], 'type' => $a['type']); if (@$a['data'] instanceof TnefAttachment) { $file['data'] = $a['data']->getData(); } else { // only fetch the body if necessary $self = $this; $file['data'] = function () use($self, $mid, $a) { return $self->decode(imap_fetchbody($self->mbox, $mid, $a['index']), $a['encoding']); }; } // Include the Content-Id if specified (for inline images) $file['cid'] = isset($a['cid']) ? $a['cid'] : false; // Validate and save immediately try { $file['id'] = $fileField->uploadAttachment($file); } catch (FileUploadError $ex) { $file['error'] = $file['name'] . ': ' . $ex->getMessage(); } $vars['attachments'][] = $file; } } // Allow signal handlers to interact with the message decoding Signal::send('mail.processed', $this, $vars); $seen = false; if (($thread = ThreadEntry::lookupByEmailHeaders($vars, $seen)) && ($t = $thread->getTicket()) && ($vars['staffId'] || !$t->isClosed() || $t->isReopenable()) && ($message = $thread->postEmail($vars))) { if (!$message instanceof ThreadEntry) { // Email has been processed previously return $message; } $ticket = $message->getTicket(); } elseif ($seen) { // Already processed, but for some reason (like rejection), no // thread item was created. Ignore the email return true; } elseif ($ticket = Ticket::create($vars, $errors, 'Email')) { $message = $ticket->getLastMessage(); } else { //Report success if the email was absolutely rejected. if (isset($errors['errno']) && $errors['errno'] == 403) { // Never process this email again! ThreadEntry::logEmailHeaders(0, $vars['mid']); return true; } // Log an error to the system logs $mailbox = Email::lookup($vars['emailId']); $ost->logError(_S('Mail Processing Exception'), sprintf(_S("Mailbox: %s | Error(s): %s"), $mailbox->getEmail(), print_r($errors, true)), false); // Indicate failure of mail processing return null; } return $ticket; }
" title="Sort By Department"><?php echo __('Department'); ?> </a> </th> <th width="120"> Localizador </th> <th width="120"> Status </th> </tr> </thead> <tbody> <?php $subject_field = TicketForm::objects()->one()->getField('subject'); if ($res && ($num = db_num_rows($res))) { $defaultDept = Dept::getDefaultDeptName(); //Default public dept. while ($row = db_fetch_array($res)) { $dept = $row['ispublic'] ? $row['dept_name'] : $defaultDept; $subject = Format::truncate($subject_field->display($subject_field->to_php($row['subject']) ?: $row['subject']), 40); if ($row['attachments']) { $subject .= ' <span class="Icon file"></span>'; } $ticketNumber = $row['number']; if ($row['isanswered'] && !strcasecmp($row['state'], 'open')) { $subject = "<b>{$subject}</b>"; $ticketNumber = "<b>{$ticketNumber}</b>"; } ?>
?> <table width="800" cellpadding="1" cellspacing="0" border="0" id="ticketInfo"> <tr> <td colspan="2" width="100%"> <h1> <a href="tickets.php?id=<?php echo $ticket->getId(); ?> " title="<?php echo __('Reload'); ?> "><i class="refresh icon-refresh"></i></a> <b> <?php $subject_field = TicketForm::getInstance()->getField('subject'); echo $subject_field->display($ticket->getSubject()); ?> </b> <small>#<?php echo $ticket->getNumber(); ?> </small> <div class="pull-right"> <a class="action-button" href="tickets.php?a=print&id=<?php echo $ticket->getId(); ?> "><i class="icon-print"></i> <?php echo __('Print'); ?> </a>