Working on reply endpoint. Just need to send out the email.

master^2
Mike Koch 6 years ago
parent 669edf832c
commit 9ae259dff6
No known key found for this signature in database
GPG Key ID: 9DF46195699C8A67

@ -4,6 +4,7 @@ namespace BusinessLogic\Tickets;
class CreateReplyRequest {
public $ticketId;
public $trackingId;
public $emailAddress;
public $replyMessage;

@ -4,13 +4,19 @@ namespace BusinessLogic\Tickets;
use BusinessLogic\Emails\EmailSenderHelper;
use BusinessLogic\Emails\EmailTemplateRetriever;
use BusinessLogic\Exceptions\ApiFriendlyException;
use BusinessLogic\Exceptions\ValidationException;
use BusinessLogic\Helpers;
use BusinessLogic\Security\UserContext;
use BusinessLogic\Statuses\Closable;
use BusinessLogic\Statuses\DefaultStatusForAction;
use BusinessLogic\ValidationModel;
use DataAccess\AuditTrail\AuditTrailGateway;
use DataAccess\Security\LoginGateway;
use DataAccess\Security\UserGateway;
use DataAccess\Statuses\StatusGateway;
use DataAccess\Tickets\ReplyGateway;
use DataAccess\Tickets\TicketGateway;
class ReplyCreator {
@ -19,17 +25,23 @@ class ReplyCreator {
private $emailSenderHelper;
private $userGateway;
private $auditTrailGateway;
private $loginGateway;
private $replyGateway;
public function __construct(StatusGateway $statusGateway,
TicketGateway $ticketGateway,
EmailSenderHelper $emailSenderHelper,
UserGateway $userGateway,
AuditTrailGateway $auditTrailGateway) {
AuditTrailGateway $auditTrailGateway,
LoginGateway $loginGateway,
ReplyGateway $replyGateway) {
$this->statusGateway = $statusGateway;
$this->ticketGateway = $ticketGateway;
$this->emailSenderHelper = $emailSenderHelper;
$this->userGateway = $userGateway;
$this->auditTrailGateway = $auditTrailGateway;
$this->loginGateway = $loginGateway;
$this->replyGateway = $replyGateway;
}
/**
@ -38,6 +50,7 @@ class ReplyCreator {
* @param $modsForHeskSettings array
* @param $userContext UserContext
* @throws ApiFriendlyException
* @throws \Exception
*/
function createReplyByCustomer($replyRequest, $heskSettings, $modsForHeskSettings, $userContext) {
$ticket = $this->ticketGateway->getTicketByTrackingId($replyRequest->trackingId, $heskSettings);
@ -50,11 +63,44 @@ class ReplyCreator {
$validationModel = new ValidationModel();
if (!strlen($replyRequest->replyMessage)) {
$validationModel->errorKeys[] = 'MESSAGE_REQUIRED';
throw new ValidationException($validationModel);
}
if ($modsForHeskSettings['rich_text_for_tickets_for_customers']) {
$replyRequest->replyMessage = Helpers::heskMakeUrl($replyRequest->replyMessage);
$replyRequest->replyMessage = nl2br($replyRequest->replyMessage);
}
if ($this->loginGateway->isIpLockedOut($replyRequest->ipAddress, $heskSettings)) {
throw new ApiFriendlyException("The IP address entered has been locked out of the system for {$heskSettings['attempt_banmin']} minutes because of too many login failures",
"Locked Out",
403);
}
if ($this->ticketGateway->areRepliesBeingFlooded($replyRequest->ticketId, $replyRequest->ipAddress, $heskSettings)) {
throw new ApiFriendlyException("You have been locked out of the system for {$heskSettings['attempt_banmin']} minutes because of too many replies to a ticket.",
"Locked Out",
403);
}
// If staff hasn't replied yet, don't change the status; otherwise set it to the status for customer replies
$currentStatus = $this->statusGateway->getStatusById($ticket->statusId, $heskSettings);
if ($currentStatus->closable === Closable::YES || $currentStatus->closable === Closable::CUSTOMERS_ONLY) {
$customerReplyStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::CUSTOMER_REPLY, $heskSettings);
$defaultNewTicketStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings);
$ticket->statusId = $ticket->statusId === $defaultNewTicketStatus->id ?
$defaultNewTicketStatus->id :
$customerReplyStatus->id;
}
$this->ticketGateway->updateMetadataForReply($ticket->id, $ticket->statusId, $heskSettings);
$this->replyGateway->insertReply($ticket->id, $ticket->name, $replyRequest->replyMessage, $replyRequest->hasHtml, $heskSettings);
//-- Changing the ticket message to the reply's
$ticket->message = $replyRequest->replyMessage;
// TODO Send the email.
}
}

@ -0,0 +1,24 @@
<?php
namespace Controllers\Tickets;
use BusinessLogic\Helpers;
use BusinessLogic\Tickets\CreateReplyRequest;
use Controllers\JsonRetriever;
class CustomerReplyController extends \BaseClass {
function post($ticketId) {
global $applicationContext, $hesk_settings;
$jsonRequest = JsonRetriever::getJsonData();
$createReplyByCustomerModel = new CreateReplyRequest();
$createReplyByCustomerModel->id = $ticketId;
$createReplyByCustomerModel->emailAddress = Helpers::safeArrayGet($jsonRequest, 'email');
$createReplyByCustomerModel->trackingId = Helpers::safeArrayGet($jsonRequest, 'trackingId');
$createReplyByCustomerModel->replyMessage = Helpers::safeArrayGet($jsonRequest, 'message');
$createReplyByCustomerModel->hasHtml = Helpers::safeArrayGet($jsonRequest, 'html');
$createReplyByCustomerModel->ipAddress = Helpers::safeArrayGet($jsonRequest, 'ip');
}
}

@ -0,0 +1,24 @@
<?php
namespace DataAccess\Security;
use DataAccess\CommonDao;
class LoginGateway extends CommonDao {
function isIpLockedOut($ipAddress, $heskSettings) {
$this->init();
$rs = hesk_dbQuery("SELECT `number` FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "logins`
WHERE `ip` = '" . hesk_dbEscape($ipAddress) . "'
AND `last_attempt` IS NOT NULL
AND DATE_ADD(`last_attempt`, INTERVAL ".intval($heskSettings['attempt_banmin'])." MINUTE ) > NOW() LIMIT 1");
$result = hesk_dbNumRows($rs) == 1 &&
hesk_dbResult($rs) >= $heskSettings['attempt_limit'];
$this->close();
return $result;
}
}

@ -53,4 +53,22 @@ class StatusGateway extends CommonDao {
return $statuses;
}
function getStatusById($id, $heskSettings) {
$this->init();
$metaRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "statuses` WHERE `ID` = " . $id);
$status = null;
if ($row = hesk_dbFetchAssoc($metaRs)) {
$languageRs = hesk_dbQuery("SELECT * FROM `" . hesk_dbEscape($heskSettings['db_pfix']) . "text_to_status_xref`
WHERE `status_id` = " . intval($row['ID']));
$status = Status::fromDatabase($row, $languageRs);
}
$this->close();
return $status;
}
}

@ -0,0 +1,17 @@
<?php
namespace DataAccess\Tickets;
use DataAccess\CommonDao;
class ReplyGateway extends CommonDao {
function insertReply($ticketId, $name, $message, $html, $heskSettings) {
$this->init();
hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($heskSettings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`, `html`)
VALUES ({$ticketId},'" . hesk_dbEscape($name) . "','" . hesk_dbEscape($message) . "',NOW(),'','" . $html . "')");
$this->close();
}
}

@ -454,4 +454,34 @@ class TicketGateway extends CommonDao {
$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();
}
}

@ -199,6 +199,7 @@ Link::all(array(
'/v1-internal/categories/{i}/sort/{s}' => action(\Controllers\Categories\CategoryController::clazz() . '::sort', array(RequestMethod::POST), SecurityHandler::INTERNAL),
// Tickets
'/v1/tickets' => action(\Controllers\Tickets\CustomerTicketController::clazz(), RequestMethod::all(), SecurityHandler::OPEN),
'/v1/tickets/{i}/replies' => action(\Controllers\Tickets\CustomerReplyController::clazz(), array(RequestMethod::POST), SecurityHandler::OPEN),
// Tickets - Staff
'/v1/staff/tickets/{i}' => action(\Controllers\Tickets\StaffTicketController::clazz(), RequestMethod::all()),
'/v1/staff/tickets/{i}/due-date' => action(\Controllers\Tickets\StaffTicketController::clazz() . '::updateDueDate', array(RequestMethod::PATCH), SecurityHandler::INTERNAL_OR_AUTH_TOKEN),

Loading…
Cancel
Save