You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
498 lines
18 KiB
PHP
498 lines
18 KiB
PHP
<?php
|
|
|
|
namespace DataAccess\Tickets;
|
|
|
|
|
|
use BusinessLogic\Attachments\AttachmentType;
|
|
use BusinessLogic\Tickets\Attachment;
|
|
use BusinessLogic\Tickets\AuditTrail;
|
|
use BusinessLogic\Tickets\AuditTrailEntityType;
|
|
use BusinessLogic\Tickets\Ticket;
|
|
use BusinessLogic\Tickets\TicketGatewayGeneratedFields;
|
|
use DataAccess\CommonDao;
|
|
|
|
class TicketGateway extends CommonDao {
|
|
/**
|
|
* @param $id int
|
|
* @param $heskSettings array
|
|
* @return Ticket|null
|
|
*/
|
|
function getTicketById($id, $heskSettings) {
|
|
$this->init();
|
|
|
|
$rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `id` = " . intval($id));
|
|
|
|
if (hesk_dbNumRows($rs) === 0) {
|
|
return null;
|
|
}
|
|
|
|
$row = hesk_dbFetchAssoc($rs);
|
|
$linkedTicketsRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `parent` = " . intval($id));
|
|
|
|
$repliesRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($id) . " ORDER BY `id` ASC");
|
|
|
|
$auditTrailRs = hesk_dbQuery("SELECT `audit`.`id`, `audit`.`language_key`, `audit`.`date`,
|
|
`values`.`replacement_index`, `values`.`replacement_value`
|
|
FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "audit_trail` AS `audit`
|
|
LEFT JOIN `" . hesk_dbEscape($heskSettings['db_pfix']) . "audit_trail_to_replacement_values` AS `values`
|
|
ON `audit`.`id` = `values`.`audit_trail_id`
|
|
WHERE `entity_type` = 'TICKET' AND `entity_id` = " . intval($id) . "
|
|
ORDER BY `audit`.`date` ASC");
|
|
|
|
$auditRecords = array();
|
|
|
|
/* @var $currentAuditRecord AuditTrail|null */
|
|
$currentAuditRecord = null;
|
|
while ($auditRow = hesk_dbFetchAssoc($auditTrailRs)) {
|
|
if ($currentAuditRecord == null || $currentAuditRecord->id != $auditRow['id']) {
|
|
if ($currentAuditRecord != null) {
|
|
$auditRecords[] = $currentAuditRecord;
|
|
}
|
|
$currentAuditRecord = new AuditTrail();
|
|
$currentAuditRecord->id = $auditRow['id'];
|
|
$currentAuditRecord->entityId = $id;
|
|
$currentAuditRecord->entityType = AuditTrailEntityType::TICKET;
|
|
$currentAuditRecord->languageKey = $auditRow['language_key'];
|
|
$currentAuditRecord->date = $auditRow['date'];
|
|
$currentAuditRecord->replacementValues = array();
|
|
}
|
|
|
|
if ($auditRow['replacement_index'] != null) {
|
|
$currentAuditRecord->replacementValues[intval($auditRow['replacement_index'])] = $auditRow['replacement_value'];
|
|
}
|
|
}
|
|
|
|
if ($currentAuditRecord != null) {
|
|
$auditRecords[] = $currentAuditRecord;
|
|
}
|
|
|
|
$ticket = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $repliesRs, $auditRecords, $heskSettings);
|
|
|
|
$this->close();
|
|
|
|
return $ticket;
|
|
}
|
|
|
|
/**
|
|
* @param $emailAddress string
|
|
* @param $heskSettings array
|
|
* @return array|null
|
|
*/
|
|
function getTicketsByEmail($emailAddress, $heskSettings) {
|
|
$this->init();
|
|
|
|
$rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets`
|
|
WHERE `email` = '" . hesk_dbEscape($emailAddress) . "'");
|
|
|
|
if (hesk_dbNumRows($rs) === 0) {
|
|
return null;
|
|
}
|
|
|
|
$tickets = array();
|
|
|
|
while ($row = hesk_dbFetchAssoc($rs)) {
|
|
$linkedTicketsRs =
|
|
hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `parent` = " . intval($row['id']));
|
|
$repliesRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($row['id']) . " ORDER BY `id` ASC");
|
|
|
|
$tickets[] = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $repliesRs, $heskSettings);
|
|
}
|
|
|
|
$this->close();
|
|
|
|
return $tickets;
|
|
}
|
|
|
|
/**
|
|
* @param $trackingId string
|
|
* @param $heskSettings array
|
|
* @return bool
|
|
*/
|
|
function doesTicketExist($trackingId, $heskSettings) {
|
|
$this->init();
|
|
|
|
$rs = hesk_dbQuery("SELECT 1 FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets`
|
|
WHERE `trackid` = '" . hesk_dbEscape($trackingId) . "'");
|
|
|
|
$ticketExists = hesk_dbNumRows($rs) > 0;
|
|
|
|
$this->close();
|
|
|
|
return $ticketExists;
|
|
}
|
|
|
|
/**
|
|
* @param $trackingId string
|
|
* @param $heskSettings array
|
|
* @return Ticket|null
|
|
*/
|
|
function getTicketByTrackingId($trackingId, $heskSettings) {
|
|
$this->init();
|
|
|
|
$rs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($trackingId) . "'");
|
|
if (hesk_dbNumRows($rs) === 0) {
|
|
return null;
|
|
}
|
|
|
|
$row = hesk_dbFetchAssoc($rs);
|
|
$linkedTicketsRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `parent` = " . intval($trackingId));
|
|
$repliesRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($row['id']) . " ORDER BY `id` ASC");
|
|
|
|
$audiTrailRs = hesk_dbQuery("SELECT `audit`.`id`, `audit`.`language_key`, `audit`.`date`,
|
|
`values`.`replacement_index`, `values`.`replacement_value`
|
|
FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "audit_trail` AS `audit`
|
|
LEFT JOIN `" . hesk_dbEscape($heskSettings['db_pfix']) . "audit_trail_to_replacement_values` AS `values`
|
|
ON `audit`.`id` = `values`.`audit_trail_id`
|
|
WHERE `entity_type` = 'TICKET' AND `entity_id` = " . intval($row['id']));
|
|
$auditRecords = array();
|
|
|
|
/* @var $currentAuditRecord AuditTrail */
|
|
$currentAuditRecord = null;
|
|
while ($auditRow = hesk_dbFetchAssoc($audiTrailRs)) {
|
|
if ($currentAuditRecord == null || $currentAuditRecord->id != $auditRow['id']) {
|
|
if ($currentAuditRecord != null) {
|
|
$auditRecords[] = $currentAuditRecord;
|
|
}
|
|
$currentAuditRecord = new AuditTrail();
|
|
$currentAuditRecord->id = $auditRow['id'];
|
|
$currentAuditRecord->entityId = $row['id'];
|
|
$currentAuditRecord->entityType = AuditTrailEntityType::TICKET;
|
|
$currentAuditRecord->languageKey = $auditRow['language_key'];
|
|
$currentAuditRecord->date = $auditRow['date'];
|
|
$currentAuditRecord->replacementValues = array();
|
|
}
|
|
|
|
if ($auditRow['replacement_index'] != null) {
|
|
$currentAuditRecord->replacementValues[intval($auditRow['replacement_index'])] = $auditRow['replacement_value'];
|
|
}
|
|
}
|
|
|
|
if ($currentAuditRecord != null) {
|
|
$auditRecords[] = $currentAuditRecord;
|
|
}
|
|
|
|
$ticket = Ticket::fromDatabaseRow($row, $linkedTicketsRs, $repliesRs, $auditRecords, $heskSettings);
|
|
|
|
$this->close();
|
|
|
|
return $ticket;
|
|
}
|
|
|
|
/**
|
|
* @param $trackingId string
|
|
* @param $heskSettings array
|
|
* @return Ticket|null
|
|
*/
|
|
function getTicketByMergedTrackingId($trackingId, $heskSettings) {
|
|
$this->init();
|
|
|
|
$rs = hesk_dbQuery("SELECT `trackid` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `merged` LIKE '%#" . hesk_dbEscape($trackingId) . "#%'");
|
|
if (hesk_dbNumRows($rs) === 0) {
|
|
return null;
|
|
}
|
|
$row = hesk_dbFetchAssoc($rs);
|
|
$actualTrackingId = $row['trackid'];
|
|
|
|
$this->close();
|
|
|
|
return $this->getTicketByTrackingId($actualTrackingId, $heskSettings);
|
|
}
|
|
|
|
/**
|
|
* @param $ticket Ticket
|
|
* @param $isEmailVerified
|
|
* @param $heskSettings
|
|
* @return TicketGatewayGeneratedFields
|
|
*/
|
|
function createTicket($ticket, $isEmailVerified, $heskSettings) {
|
|
$this->init();
|
|
|
|
$dueDate = $ticket->dueDate ? "'{$ticket->dueDate}'" : "NULL";
|
|
// Prepare SQL for custom fields
|
|
$customWhere = '';
|
|
$customWhat = '';
|
|
|
|
// Need to insert "addigned by" value?
|
|
if ($ticket->assignedBy !== null) {
|
|
$abWhere = ', `assignedby` ';
|
|
$abWhat = ', ' . intval($ticket->assignedBy);
|
|
} else {
|
|
$abWhere = '';
|
|
$abWhat = '';
|
|
}
|
|
|
|
for ($i=1; $i<=50; $i++)
|
|
{
|
|
$customWhere .= ", `custom{$i}`";
|
|
$customWhat .= ", '" . (isset($ticket->customFields[$i]) ? hesk_dbEscape($ticket->customFields[$i]) : '') . "'";
|
|
}
|
|
|
|
$suggestedArticles = 'NULL';
|
|
if ($ticket->suggestedArticles !== null && !empty($ticket->suggestedArticles)) {
|
|
$suggestedArticles = "'" .implode(',', $ticket->suggestedArticles) . "'";
|
|
}
|
|
|
|
$latitude = $ticket->location !== null
|
|
&& isset($ticket->location[0])
|
|
&& $ticket->location[0] !== null ? $ticket->location[0] : 'E-0';
|
|
$longitude = $ticket->location !== null
|
|
&& isset($ticket->location[1])
|
|
&& $ticket->location[1] !== null ? $ticket->location[1] : 'E-0';
|
|
$userAgent = $ticket->userAgent !== null ? $ticket->userAgent : '';
|
|
$screenResolutionWidth = $ticket->screenResolution !== null
|
|
&& isset($ticket->screenResolution[0])
|
|
&& $ticket->screenResolution[0] !== null ? intval($ticket->screenResolution[0]) : 'NULL';
|
|
$screenResolutionHeight = $ticket->screenResolution !== null
|
|
&& isset($ticket->screenResolution[1])
|
|
&& $ticket->screenResolution[1] !== null ? intval($ticket->screenResolution[1]) : 'NULL';
|
|
|
|
$ipAddress = $ticket->ipAddress !== null
|
|
&& $ticket->ipAddress !== '' ? $ticket->ipAddress : '';
|
|
|
|
$emailAddresses = implode(';', $ticket->email);
|
|
|
|
$tableName = $isEmailVerified ? 'tickets' : 'stage_tickets';
|
|
|
|
$sql = "INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . $tableName ."`
|
|
(
|
|
`trackid`,
|
|
`name`,
|
|
`email`,
|
|
`category`,
|
|
`priority`,
|
|
`subject`,
|
|
`message`,
|
|
`dt`,
|
|
`lastchange`,
|
|
`articles`,
|
|
`ip`,
|
|
`language`,
|
|
`openedby`,
|
|
`owner`,
|
|
`attachments`,
|
|
`merged`,
|
|
`status`,
|
|
`latitude`,
|
|
`longitude`,
|
|
`html`,
|
|
`user_agent`,
|
|
`screen_resolution_height`,
|
|
`screen_resolution_width`,
|
|
`due_date`,
|
|
`history`
|
|
{$customWhere}
|
|
{$abWhere}
|
|
)
|
|
VALUES
|
|
(
|
|
'" . hesk_dbEscape($ticket->trackingId) . "',
|
|
'" . hesk_dbEscape($ticket->name) . "',
|
|
'" . hesk_dbEscape($emailAddresses) . "',
|
|
'" . intval($ticket->categoryId) . "',
|
|
'" . intval($ticket->priorityId) . "',
|
|
'" . hesk_dbEscape($ticket->subject) . "',
|
|
'" . hesk_dbEscape($ticket->message) . "',
|
|
NOW(),
|
|
NOW(),
|
|
" . $suggestedArticles . ",
|
|
'" . hesk_dbEscape($ipAddress) . "',
|
|
'" . hesk_dbEscape($ticket->language) . "',
|
|
'" . intval($ticket->openedBy) . "',
|
|
'" . intval($ticket->ownerId) . "',
|
|
'" . hesk_dbEscape($ticket->getAttachmentsForDatabase()) . "',
|
|
'',
|
|
" . intval($ticket->statusId) . ",
|
|
'" . hesk_dbEscape($latitude) . "',
|
|
'" . hesk_dbEscape($longitude) . "',
|
|
'" . hesk_dbEscape($ticket->usesHtml) . "',
|
|
'" . hesk_dbEscape($userAgent) . "',
|
|
" . hesk_dbEscape($screenResolutionHeight) . ",
|
|
" . hesk_dbEscape($screenResolutionWidth) . ",
|
|
{$dueDate},
|
|
'" . hesk_dbEscape($ticket->auditTrailHtml) . "'
|
|
{$customWhat}
|
|
{$abWhat}
|
|
)
|
|
";
|
|
|
|
hesk_dbQuery($sql);
|
|
$id = hesk_dbInsertID();
|
|
|
|
$rs = hesk_dbQuery('SELECT `dt`, `lastchange` FROM `' . hesk_dbEscape($heskSettings['db_pfix']) . $tableName .'` WHERE `id` = ' . intval($id));
|
|
$row = hesk_dbFetchAssoc($rs);
|
|
|
|
$generatedFields = new TicketGatewayGeneratedFields();
|
|
$generatedFields->id = $id;
|
|
$generatedFields->dateCreated = hesk_date($row['dt'], true);
|
|
$generatedFields->dateModified = hesk_date($row['lastchange'], true);
|
|
|
|
$this->close();
|
|
|
|
return $generatedFields;
|
|
}
|
|
|
|
/**
|
|
* @param $ticketId int
|
|
* @param $attachments Attachment[]
|
|
* @param $heskSettings array
|
|
*
|
|
* Crappy logic that should just be pulled from the attachments table, but using for backwards compatibility
|
|
*/
|
|
function updateAttachmentsForTicket($ticketId, $attachments, $heskSettings) {
|
|
$this->init();
|
|
$this->updateAttachmentsFor($ticketId, $attachments, AttachmentType::MESSAGE, $heskSettings);
|
|
$this->close();
|
|
}
|
|
|
|
private function updateAttachmentsFor($id, $attachments, $attachmentType, $heskSettings) {
|
|
$attachmentStrings = array();
|
|
foreach ($attachments as $attachment) {
|
|
$attachmentStrings[] = "{$attachment->id}#{$attachment->fileName}#{$attachment->savedName}";
|
|
}
|
|
$attachmentStringToSave = implode(',', $attachmentStrings);
|
|
|
|
$tableName = $attachmentType == AttachmentType::MESSAGE ? 'tickets' : 'replies';
|
|
|
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . $tableName . "`
|
|
SET `attachments` = '" . hesk_dbEscape($attachmentStringToSave) . "'
|
|
WHERE `id` = " . intval($id));
|
|
}
|
|
|
|
/**
|
|
* @param $replyId int
|
|
* @param $attachments Attachment[]
|
|
* @param $heskSettings array
|
|
*
|
|
* Crappy logic that should just be pulled from the attachments table, but using for backwards compatibility
|
|
*/
|
|
function updateAttachmentsForReply($replyId, $attachments, $heskSettings) {
|
|
$this->init();
|
|
$this->updateAttachmentsFor($replyId, $attachments, AttachmentType::REPLY, $heskSettings);
|
|
$this->close();
|
|
}
|
|
|
|
function deleteRepliesForTicket($ticketId, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto` = " . intval($ticketId));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
function deleteReplyDraftsForTicket($ticketId, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "reply_drafts` WHERE `ticket`=" . intval($ticketId));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
function deleteNotesForTicket($ticketId, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "notes` WHERE `ticket`='" . intval($ticketId) . "'");
|
|
|
|
$this->close();
|
|
}
|
|
|
|
/**
|
|
* @param $ticketId int
|
|
* @param $heskSettings array
|
|
*/
|
|
function deleteTicket($ticketId, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` WHERE `id` = " . intval($ticketId));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
/**
|
|
* @param $ticket Ticket
|
|
* @param $heskSettings array
|
|
*/
|
|
function updateBasicTicketInfo($ticket, $heskSettings) {
|
|
$this->init();
|
|
|
|
// Escaped vars
|
|
$subject = hesk_dbEscape($ticket->subject);
|
|
$message = hesk_dbEscape($ticket->message);
|
|
$language = hesk_dbEscape($ticket->language);
|
|
$name = hesk_dbEscape($ticket->name);
|
|
$email = hesk_dbEscape($ticket->email);
|
|
|
|
// Prepare SQL for custom fields
|
|
$customSql = '';
|
|
|
|
for ($i=1; $i<=50; $i++)
|
|
{
|
|
$customSql .= ", `custom{$i}` = '" . (isset($ticket->customFields[$i]) ? hesk_dbEscape($ticket->customFields[$i]) : '') . "'";
|
|
}
|
|
|
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets`
|
|
SET `subject` = '{$subject}',
|
|
`message` = '{$message}',
|
|
`language` = '{$language}',
|
|
`name` = '{$name}',
|
|
`email` = '{$email}',
|
|
`html` = " . ($ticket->usesHtml ? 1 : 0) . ",
|
|
{$customSql}
|
|
WHERE `id` = " . intval($ticket->id));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
function moveTicketsToDefaultCategory($oldCategoryId, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets`
|
|
SET `category` = 1
|
|
WHERE `category` = " . intval($oldCategoryId));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
function updateTicketDueDate($id, $dueDate, $heskSettings) {
|
|
$this->init();
|
|
|
|
$sqlDueDate = 'NULL';
|
|
if ($dueDate != NULL) {
|
|
$sqlDueDate = "'" . date('Y-m-d H:i:s', strtotime($dueDate)) . "'";
|
|
}
|
|
|
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` SET `due_date` = {$sqlDueDate}
|
|
WHERE `id` = " . intval($id));
|
|
|
|
$this->close();
|
|
}
|
|
|
|
function areRepliesBeingFlooded($id, $ip, $heskSettings) {
|
|
$this->init();
|
|
|
|
$result = false;
|
|
$res = hesk_dbQuery("SELECT `staffid` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` WHERE `replyto`='{$id}' AND `dt` > DATE_SUB(NOW(), INTERVAL 10 MINUTE) ORDER BY `id` ASC");
|
|
if (hesk_dbNumRows($res) > 0) {
|
|
$sequential_customer_replies = 0;
|
|
while ($tmp = hesk_dbFetchAssoc($res)) {
|
|
$sequential_customer_replies = $tmp['staffid'] ? 0 : $sequential_customer_replies + 1;
|
|
}
|
|
|
|
if ($sequential_customer_replies > 10) {
|
|
hesk_dbQuery("INSERT INTO `".hesk_dbEscape($heskSettings['db_pfix'])."logins` (`ip`, `number`) VALUES ('".hesk_dbEscape($ip)."', ".intval($heskSettings['attempt_limit'] + 1).")");
|
|
$result = true;
|
|
}
|
|
}
|
|
|
|
$this->close();
|
|
|
|
return $result;
|
|
}
|
|
|
|
function updateMetadataForReply($id, $status, $heskSettings) {
|
|
$this->init();
|
|
|
|
hesk_dbQuery("UPDATE `" . hesk_dbEscape($heskSettings['db_pfix']) . "tickets` SET `lastchange`=NOW(), `status`='{$status}', `replies`=`replies`+1, `lastreplier`='0' WHERE `id`='{$id}'");
|
|
|
|
$this->close();
|
|
}
|
|
} |