From 9654fd38cb43ea648c46e3c3e452b8752de7a9ed Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 01:12:33 -0400 Subject: [PATCH 01/52] Created hacky web service to return basic ticket information --- web-services/models/ticket.php | 51 +++++++++++ .../repositories/ticketRepository.php | 84 +++++++++++++++++++ web-services/ticket/index.php | 24 ++++++ 3 files changed, 159 insertions(+) create mode 100644 web-services/models/ticket.php create mode 100644 web-services/repositories/ticketRepository.php create mode 100644 web-services/ticket/index.php diff --git a/web-services/models/ticket.php b/web-services/models/ticket.php new file mode 100644 index 00000000..78e9ef75 --- /dev/null +++ b/web-services/models/ticket.php @@ -0,0 +1,51 @@ + diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php new file mode 100644 index 00000000..93c2566d --- /dev/null +++ b/web-services/repositories/ticketRepository.php @@ -0,0 +1,84 @@ +connect_error) + { + return ('An error occured when establishing a connection to the database.'); + } + + $sql = 'SELECT * FROM '.$settings['db_pfix'].'tickets WHERE id = '.$id; + $results = $connection->query($sql); + + //-- There will only ever be one result, as ID is the primary key on the tickets table. + $result = $results->fetch_assoc(); + + $ticket = new Ticket(); + + $ticket->id = $result['id']; + $ticket->trackingId = $result['trackid']; + $ticket->name = $result['name']; + $ticket->email = $result['email']; + $ticket->category = $result['category']; + $ticket->priority = $result['priority']; + $ticket->subject = $result['subject']; + $ticket->message = $result['message']; + $ticket->dateCreated = $result['dt']; + $ticket->dateModified = $result['lastchange']; + $ticket->ip = $result['ip']; + $ticket->language = $result['language']; + $ticket->status = $result['status']; + $ticket->owner = $result['owner']; + $ticket->timeWorked = $result['time_worked']; + $ticket->lastReplier = $result['lastreplier']; + $ticket->replierId = $result['replierid']; + $ticket->isArchived = $result['archive']; + $ticket->isLocked = $result['locked']; + $ticket->attachments = $result['attachments']; + $ticket->merged = $result['merged']; + + //-- Not currently returning history, as it can contain a metric shit-ton of HTML code and will cludder up the JSON response. + //$ticket->history = $result['history']; + $ticket->custom1 = $result['custom1']; + $ticket->custom2 = $result['custom2']; + $ticket->custom3 = $result['custom3']; + $ticket->custom4 = $result['custom4']; + $ticket->custom5 = $result['custom5']; + $ticket->custom6 = $result['custom6']; + $ticket->custom7 = $result['custom7']; + $ticket->custom8 = $result['custom8']; + $ticket->custom9 = $result['custom9']; + $ticket->custom10 = $result['custom10']; + $ticket->custom11 = $result['custom11']; + $ticket->custom12 = $result['custom12']; + $ticket->custom13 = $result['custom13']; + $ticket->custom14 = $result['custom14']; + $ticket->custom15 = $result['custom15']; + $ticket->custom16 = $result['custom16']; + $ticket->custom17 = $result['custom17']; + $ticket->custom18 = $result['custom18']; + $ticket->custom19 = $result['custom19']; + $ticket->custom20 = $result['custom20']; + + return $ticket; + } +} + +?> diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php new file mode 100644 index 00000000..5049e044 --- /dev/null +++ b/web-services/ticket/index.php @@ -0,0 +1,24 @@ +getTicketForId(13, $hesk_settings); + //--A quick and dirty RESTful test using PHP. + echo json_encode($ticket); +} +else +{ + header(http_response_code(400)); +} + +?> From 404aea6318b1c722b2a5f30d8d70713d61186e36 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 10:52:51 -0400 Subject: [PATCH 02/52] Ticket ID to retrieve is no longer hard-coded --- web-services/ticket/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php index 5049e044..f818e0d6 100644 --- a/web-services/ticket/index.php +++ b/web-services/ticket/index.php @@ -12,7 +12,7 @@ if(isset($_GET['id'])) { $ticketRepository = TicketRepository::getInstance(); - $ticket = $ticketRepository->getTicketForId(13, $hesk_settings); + $ticket = $ticketRepository->getTicketForId($_GET['id'], $hesk_settings); //--A quick and dirty RESTful test using PHP. echo json_encode($ticket); } From 34163f2c1d8a1add4229771b5c19dbb6903c75c9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:25:40 -0400 Subject: [PATCH 03/52] Now more specific/readable information is returned --- .../repositories/ticketRepository.php | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index 93c2566d..ddffd6ac 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -24,7 +24,52 @@ class TicketRepository { return ('An error occured when establishing a connection to the database.'); } - $sql = 'SELECT * FROM '.$settings['db_pfix'].'tickets WHERE id = '.$id; + $sql = 'SELECT T.id, '. + 'T.trackid, '. + 'T.name AS "ContactName", '. + 'T.email, '. + 'C.name AS "CategoryName", '. + 'T.priority, '. + 'T.subject, '. + 'T.message, '. + 'T.dt, '. + 'T.lastchange, '. + 'T.ip, '. + 'T.language, '. + 'T.status, '. + 'U.name AS "Owner", '. + 'T.time_worked, '. + 'T.lastreplier, '. + 'U2.name AS "LastReplierName", '. + 'T.archive, '. + 'T.locked, '. + 'T.attachments, '. + 'T.merged, '. + 'T.custom1, '. + 'T.custom2, '. + 'T.custom3, '. + 'T.custom4, '. + 'T.custom5, '. + 'T.custom6, '. + 'T.custom7, '. + 'T.custom8, '. + 'T.custom9, '. + 'T.custom10, '. + 'T.custom11, '. + 'T.custom12, '. + 'T.custom13, '. + 'T.custom14, '. + 'T.custom15, '. + 'T.custom16, '. + 'T.custom17, '. + 'T.custom18, '. + 'T.custom19, '. + 'T.custom20 '. + 'FROM '.$settings['db_pfix'].'tickets T '. + 'INNER JOIN '.$settings['db_pfix'].'categories C ON C.id = T.category '. + 'LEFT JOIN '.$settings['db_pfix'].'users U ON U.id = T.owner '. + 'LEFT JOIN '.$settings['db_pfix'].'users U2 ON U2.id = T.replierid '. + 'WHERE T.id = '.$id; $results = $connection->query($sql); //-- There will only ever be one result, as ID is the primary key on the tickets table. @@ -34,21 +79,21 @@ class TicketRepository { $ticket->id = $result['id']; $ticket->trackingId = $result['trackid']; - $ticket->name = $result['name']; + $ticket->name = $result['ContactName']; $ticket->email = $result['email']; - $ticket->category = $result['category']; - $ticket->priority = $result['priority']; + $ticket->category = $result['CategoryName']; + $ticket->priority = self::getPriorityForId($result['priority']); $ticket->subject = $result['subject']; $ticket->message = $result['message']; $ticket->dateCreated = $result['dt']; $ticket->dateModified = $result['lastchange']; $ticket->ip = $result['ip']; $ticket->language = $result['language']; - $ticket->status = $result['status']; - $ticket->owner = $result['owner']; + $ticket->status = self::getStatusForId($result['status']); + $ticket->owner = $result['Owner']; $ticket->timeWorked = $result['time_worked']; - $ticket->lastReplier = $result['lastreplier']; - $ticket->replierId = $result['replierid']; + $ticket->lastReplier = self::getWhoLastRepliedForId($result['lastreplier']); + $ticket->replierId = $result['LastReplierName']; $ticket->isArchived = $result['archive']; $ticket->isLocked = $result['locked']; $ticket->attachments = $result['attachments']; @@ -79,6 +124,38 @@ class TicketRepository { return $ticket; } + + public function getPriorityForId($id) { + if ($id == 0){ + return '* Critical *'; + } elseif ($id == 1){ + return 'High'; + } elseif ($id == 2){ + return 'Medium'; + } elseif ($id == 3){ + return 'Low'; + } + } + + private function getStatusForId($id) { + if ($id == 0) { + return 'New'; + } elseif ($id == 1) { + return 'Waiting Reply'; + } elseif ($id == 2) { + return 'Replied'; + } elseif ($id == 3) { + return 'Resolved'; + } elseif ($id == 4) { + return 'In Progress'; + } elseif ($id == 5) { + return 'On Hold'; + } + } + + private function getWhoLastRepliedForId($id) { + return ($id == 0 ? 'Contact' : 'Staff'); + } } ?> From 9435de19d529c61ffc7a373edf418c152aa98396 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:30:21 -0400 Subject: [PATCH 04/52] Made a public function that should be private private --- web-services/repositories/ticketRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index ddffd6ac..9d7adb33 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -125,7 +125,7 @@ class TicketRepository { return $ticket; } - public function getPriorityForId($id) { + private function getPriorityForId($id) { if ($id == 0){ return '* Critical *'; } elseif ($id == 1){ From c204e925bb5ecb92963926640685aae8bc48c8b4 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:34:34 -0400 Subject: [PATCH 05/52] Now return true/false for archived/locked --- web-services/repositories/ticketRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index 9d7adb33..d4a94490 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -94,8 +94,8 @@ class TicketRepository { $ticket->timeWorked = $result['time_worked']; $ticket->lastReplier = self::getWhoLastRepliedForId($result['lastreplier']); $ticket->replierId = $result['LastReplierName']; - $ticket->isArchived = $result['archive']; - $ticket->isLocked = $result['locked']; + $ticket->isArchived = ($result['archive'] ? true : false); + $ticket->isLocked = ($result['locked'] ? true : false); $ticket->attachments = $result['attachments']; $ticket->merged = $result['merged']; From c63ca99ccc648016352cf83baa4c6f1cd85c72bb Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:45:33 -0400 Subject: [PATCH 06/52] Updated README.md --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2d615196..1077a681 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ [![Analytics](https://ga-beacon.appspot.com/UA-49251479-1/hesk/README)](https://github.com/mkoch227/Hesk) -

HESK UI v1.1.5

+

HESK Web Services

-This branch contains all files modified from the base version of HESK to become HESK UI, a clean user interface for HESK v2.5.3 +This branch contains additional files on top of HESK UI that create the HESK Web Services, a REST API to retrieve / submit changes to support tickets.

Download

-You can download this tweak via two ways: +There are currently no releases available, however you will eventually be able to download this tweak via two ways:
  1. Stable Releases: Releases that have a release tag associated with a commit are considered releases. You can click on "releases" on the top of the repo, and then click "zip" or "tar.gz" to download the repo at that stage.
  2. @@ -18,7 +18,7 @@ You can download this tweak via two ways:
    1. Download HESK from http://www.hesk.com/download.php.
    2. Extract the contents of HESK to a directory of your choice.
    3. -
    4. Download HESK UI from one of the two methods described above.
    5. +
    6. Download the HESK Web Services + HESK UI bundle from one of the two methods described above.
    7. Copy and paste the contents of the zip/tar.gz bundle and overwrite any files in the original HESK 2.5.3 folder.
    8. Upload the resulting folder to your webserver.
    @@ -27,8 +27,9 @@ You can download this tweak via two ways:

    Languages

    As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate HESK UI to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in HESK UI for your language.

    If you create a translation for HESK UI, please submit it via a pull request or via the PHP Junkyards forum, where it will be committed to this branch.

    +

    There are currently some hard-coded strings in the web-services folder that will also need to be translated if you wish to have the string translated.

    -

    Browser Compability

    +

    Browser Compability for HESK UI

    This list may be incomplete. Please leave a note on the PHP Junkyard forums for additional browser compatibility information.

    • Google Chrome 33+: Compatible
    • @@ -38,6 +39,7 @@ You can download this tweak via two ways:
    • Internet Explorer 9: Compatible

    There are no intentions of making HESK UI compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

    +

    Browser compatibility: any browser / application capable of reading a JSON response.

    Versioning

    HESK UI will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

    From 1fd00cf40e7b700a4348b0cfc0ca734190a1982f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:46:07 -0400 Subject: [PATCH 07/52] fixed name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1077a681..2a4be37b 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ There are currently no releases available, however you will eventually be able t

    Browser compatibility: any browser / application capable of reading a JSON response.

    Versioning

    -

    HESK UI will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

    +

    HESK Web Services will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

    <major>.<minor>.<patch> From 01ccbde4f36537904ac1f40c65a788d26d9e93c1 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 8 Jun 2014 11:46:34 -0400 Subject: [PATCH 08/52] added name for clarity --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a4be37b..a6546814 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ There are currently no releases available, however you will eventually be able t
  3. Internet Explorer 9: Compatible
  4. There are no intentions of making HESK UI compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

    -

    Browser compatibility: any browser / application capable of reading a JSON response.

    +

    Browser compatibility for HESK Web Services: any browser / application capable of reading a JSON response.

    Versioning

    HESK Web Services will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

    From 8e48a431af55824de2d342ebcbf6d07596368ef0 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 6 Jul 2014 19:20:07 -0400 Subject: [PATCH 09/52] Switched getTicketForId to a static method; no more need for singleton --- web-services/repositories/ticketRepository.php | 11 +---------- web-services/ticket/index.php | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index d4a94490..18d0f082 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -7,16 +7,7 @@ class TicketRepository { private function __construct() { } - public static function getInstance() { - static $instance = null; - if ($instance == null) - { - $instance = new TicketRepository(); - } - return $instance; - } - - public function getTicketForId($id, $settings) { + public static function getTicketForId($id, $settings) { $connection = new mysqli($settings['db_host'], $settings['db_user'], $settings['db_pass'], $settings['db_name']); if ($connection->connect_error) diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php index f818e0d6..66310ee9 100644 --- a/web-services/ticket/index.php +++ b/web-services/ticket/index.php @@ -12,7 +12,7 @@ if(isset($_GET['id'])) { $ticketRepository = TicketRepository::getInstance(); - $ticket = $ticketRepository->getTicketForId($_GET['id'], $hesk_settings); + $ticket = TicketRepository::getTicketForId($_GET['id'], $hesk_settings); //--A quick and dirty RESTful test using PHP. echo json_encode($ticket); } From 1f1c6071bb9538df87dc5086e8e66e85ce4f2707 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 6 Jul 2014 19:20:30 -0400 Subject: [PATCH 10/52] Set variable types and return just IDs; other repos will have mappings --- .../repositories/ticketRepository.php | 121 ++++++++---------- 1 file changed, 52 insertions(+), 69 deletions(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index 18d0f082..e0a86ae8 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -19,7 +19,7 @@ class TicketRepository { 'T.trackid, '. 'T.name AS "ContactName", '. 'T.email, '. - 'C.name AS "CategoryName", '. + 'T.category, '. 'T.priority, '. 'T.subject, '. 'T.message, '. @@ -28,10 +28,10 @@ class TicketRepository { 'T.ip, '. 'T.language, '. 'T.status, '. - 'U.name AS "Owner", '. + 'T.owner, '. 'T.time_worked, '. 'T.lastreplier, '. - 'U2.name AS "LastReplierName", '. + 'T.replierid, '. 'T.archive, '. 'T.locked, '. 'T.attachments, '. @@ -57,9 +57,6 @@ class TicketRepository { 'T.custom19, '. 'T.custom20 '. 'FROM '.$settings['db_pfix'].'tickets T '. - 'INNER JOIN '.$settings['db_pfix'].'categories C ON C.id = T.category '. - 'LEFT JOIN '.$settings['db_pfix'].'users U ON U.id = T.owner '. - 'LEFT JOIN '.$settings['db_pfix'].'users U2 ON U2.id = T.replierid '. 'WHERE T.id = '.$id; $results = $connection->query($sql); @@ -68,85 +65,71 @@ class TicketRepository { $ticket = new Ticket(); + settype($result['id'], 'int'); $ticket->id = $result['id']; + $ticket->trackingId = $result['trackid']; $ticket->name = $result['ContactName']; $ticket->email = $result['email']; - $ticket->category = $result['CategoryName']; - $ticket->priority = self::getPriorityForId($result['priority']); + + settype($result['category'], 'int'); + $ticket->category = $result['category']; + + settype($result['priority'], 'int'); + $ticket->priority = $result['priority']; + $ticket->subject = $result['subject']; $ticket->message = $result['message']; - $ticket->dateCreated = $result['dt']; - $ticket->dateModified = $result['lastchange']; + + //-- Convert these to times so the receiver can use whatever format they want to display the date/time without extra work. + $ticket->dateCreated = strtotime($result['dt']); + $ticket->dateModified = strtotime($result['lastchange']); $ticket->ip = $result['ip']; $ticket->language = $result['language']; - $ticket->status = self::getStatusForId($result['status']); - $ticket->owner = $result['Owner']; + + settype($result['status'], 'int'); + $ticket->status = $result['status']; + + settype($result['owner'], 'int'); + $ticket->owner = $result['owner']; + $ticket->timeWorked = $result['time_worked']; - $ticket->lastReplier = self::getWhoLastRepliedForId($result['lastreplier']); - $ticket->replierId = $result['LastReplierName']; + + settype($result['lastreplier'], 'int'); + $ticket->lastReplier = $result['lastreplier']; + + settype($result['replierid'], 'int'); + $ticket->replierId = $result['replierid']; $ticket->isArchived = ($result['archive'] ? true : false); $ticket->isLocked = ($result['locked'] ? true : false); $ticket->attachments = $result['attachments']; - $ticket->merged = $result['merged']; + + //-- explode handles splitting the list into an array, array_filter removes the empty string elements (""), and array_values resets the indicies. + $ticket->merged = array_values(array_filter(explode('#',$result['merged']))); //-- Not currently returning history, as it can contain a metric shit-ton of HTML code and will cludder up the JSON response. //$ticket->history = $result['history']; - $ticket->custom1 = $result['custom1']; - $ticket->custom2 = $result['custom2']; - $ticket->custom3 = $result['custom3']; - $ticket->custom4 = $result['custom4']; - $ticket->custom5 = $result['custom5']; - $ticket->custom6 = $result['custom6']; - $ticket->custom7 = $result['custom7']; - $ticket->custom8 = $result['custom8']; - $ticket->custom9 = $result['custom9']; - $ticket->custom10 = $result['custom10']; - $ticket->custom11 = $result['custom11']; - $ticket->custom12 = $result['custom12']; - $ticket->custom13 = $result['custom13']; - $ticket->custom14 = $result['custom14']; - $ticket->custom15 = $result['custom15']; - $ticket->custom16 = $result['custom16']; - $ticket->custom17 = $result['custom17']; - $ticket->custom18 = $result['custom18']; - $ticket->custom19 = $result['custom19']; - $ticket->custom20 = $result['custom20']; + $ticket->custom1 = $result['custom1'] == '' ? null : $result['custom1']; + $ticket->custom2 = $result['custom2'] == '' ? null : $result['custom2']; + $ticket->custom3 = $result['custom3'] == '' ? null : $result['custom3']; + $ticket->custom4 = $result['custom4'] == '' ? null : $result['custom4']; + $ticket->custom5 = $result['custom5'] == '' ? null : $result['custom5']; + $ticket->custom6 = $result['custom6'] == '' ? null : $result['custom6']; + $ticket->custom7 = $result['custom7'] == '' ? null : $result['custom7']; + $ticket->custom8 = $result['custom8'] == '' ? null : $result['custom8']; + $ticket->custom9 = $result['custom9'] == '' ? null : $result['custom9']; + $ticket->custom10 = $result['custom10'] == '' ? null : $result['custom10']; + $ticket->custom11 = $result['custom11'] == '' ? null : $result['custom11']; + $ticket->custom12 = $result['custom12'] == '' ? null : $result['custom12']; + $ticket->custom13 = $result['custom13'] == '' ? null : $result['custom13']; + $ticket->custom14 = $result['custom14'] == '' ? null : $result['custom14']; + $ticket->custom15 = $result['custom15'] == '' ? null : $result['custom15']; + $ticket->custom16 = $result['custom16'] == '' ? null : $result['custom16']; + $ticket->custom17 = $result['custom17'] == '' ? null : $result['custom17']; + $ticket->custom18 = $result['custom18'] == '' ? null : $result['custom18']; + $ticket->custom19 = $result['custom19'] == '' ? null : $result['custom19']; + $ticket->custom20 = $result['custom20'] == '' ? null : $result['custom20']; return $ticket; } - - private function getPriorityForId($id) { - if ($id == 0){ - return '* Critical *'; - } elseif ($id == 1){ - return 'High'; - } elseif ($id == 2){ - return 'Medium'; - } elseif ($id == 3){ - return 'Low'; - } - } - - private function getStatusForId($id) { - if ($id == 0) { - return 'New'; - } elseif ($id == 1) { - return 'Waiting Reply'; - } elseif ($id == 2) { - return 'Replied'; - } elseif ($id == 3) { - return 'Resolved'; - } elseif ($id == 4) { - return 'In Progress'; - } elseif ($id == 5) { - return 'On Hold'; - } - } - - private function getWhoLastRepliedForId($id) { - return ($id == 0 ? 'Contact' : 'Staff'); - } } - -?> From bff8f0388770dcdadd0a9d69b34c58dc4f114d90 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 6 Jul 2014 21:49:03 -0400 Subject: [PATCH 11/52] Removed unused reference --- web-services/ticket/index.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php index 66310ee9..ebc97f47 100644 --- a/web-services/ticket/index.php +++ b/web-services/ticket/index.php @@ -10,8 +10,6 @@ include('/../repositories/ticketRepository.php'); if(isset($_GET['id'])) { - - $ticketRepository = TicketRepository::getInstance(); $ticket = TicketRepository::getTicketForId($_GET['id'], $hesk_settings); //--A quick and dirty RESTful test using PHP. echo json_encode($ticket); From 3d235918eac76e3c95bbad873a6208acc372fe6d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 7 Jul 2014 09:53:56 -0400 Subject: [PATCH 12/52] Now tickets can be retreived by Tracking ID via REST --- .../repositories/ticketRepository.php | 124 ++++++++++++------ web-services/ticket/index.php | 8 +- 2 files changed, 86 insertions(+), 46 deletions(-) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index e0a86ae8..51368b7b 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -2,6 +2,7 @@ require('/../models/ticket.php'); + class TicketRepository { private function __construct() { @@ -12,57 +13,49 @@ class TicketRepository { $connection = new mysqli($settings['db_host'], $settings['db_user'], $settings['db_pass'], $settings['db_name']); if ($connection->connect_error) { - return ('An error occured when establishing a connection to the database.'); + return ('An error occurred when establishing a connection to the database.'); } - $sql = 'SELECT T.id, '. - 'T.trackid, '. - 'T.name AS "ContactName", '. - 'T.email, '. - 'T.category, '. - 'T.priority, '. - 'T.subject, '. - 'T.message, '. - 'T.dt, '. - 'T.lastchange, '. - 'T.ip, '. - 'T.language, '. - 'T.status, '. - 'T.owner, '. - 'T.time_worked, '. - 'T.lastreplier, '. - 'T.replierid, '. - 'T.archive, '. - 'T.locked, '. - 'T.attachments, '. - 'T.merged, '. - 'T.custom1, '. - 'T.custom2, '. - 'T.custom3, '. - 'T.custom4, '. - 'T.custom5, '. - 'T.custom6, '. - 'T.custom7, '. - 'T.custom8, '. - 'T.custom9, '. - 'T.custom10, '. - 'T.custom11, '. - 'T.custom12, '. - 'T.custom13, '. - 'T.custom14, '. - 'T.custom15, '. - 'T.custom16, '. - 'T.custom17, '. - 'T.custom18, '. - 'T.custom19, '. - 'T.custom20 '. - 'FROM '.$settings['db_pfix'].'tickets T '. + $sql = self::getDefaultSql($settings). 'WHERE T.id = '.$id; $results = $connection->query($sql); //-- There will only ever be one result, as ID is the primary key on the tickets table. $result = $results->fetch_assoc(); + $connection->close(); + return self::generateTicketModel($result); + } + + public static function getTicketForTrackingId($id, $settings) + { + $connection = new mysqli($settings['db_host'], $settings['db_user'], $settings['db_pass'], $settings['db_name']); + if ($connection->connect_error) + { + return ('An error occurred when establishing a connection to the database.'); + } + + $sql = self::getDefaultSql($settings). + 'WHERE T.trackid = '.$id; + $results = $connection->query($sql); + + //-- There should only be one result as Tracking IDs should be unique. If there are two, return a 422 response. + if ($results->num_rows > 1) + { + header(http_response_code(422)); + return; + } elseif ($results->num_rows == 0) + { + //-- No ticket found. Return a 404. + header(http_response_code(404)); + return; + } else { + $result = $results->fetch_assoc(); + $connection->close(); + return self::generateTicketModel($result); + } + } + private static function generateTicketModel($result) { $ticket = new Ticket(); settype($result['id'], 'int'); @@ -132,4 +125,49 @@ class TicketRepository { return $ticket; } + + private function getDefaultSql($settings) { + return 'SELECT T.id, '. + 'T.trackid, '. + 'T.name AS "ContactName", '. + 'T.email, '. + 'T.category, '. + 'T.priority, '. + 'T.subject, '. + 'T.message, '. + 'T.dt, '. + 'T.lastchange, '. + 'T.ip, '. + 'T.language, '. + 'T.status, '. + 'T.owner, '. + 'T.time_worked, '. + 'T.lastreplier, '. + 'T.replierid, '. + 'T.archive, '. + 'T.locked, '. + 'T.attachments, '. + 'T.merged, '. + 'T.custom1, '. + 'T.custom2, '. + 'T.custom3, '. + 'T.custom4, '. + 'T.custom5, '. + 'T.custom6, '. + 'T.custom7, '. + 'T.custom8, '. + 'T.custom9, '. + 'T.custom10, '. + 'T.custom11, '. + 'T.custom12, '. + 'T.custom13, '. + 'T.custom14, '. + 'T.custom15, '. + 'T.custom16, '. + 'T.custom17, '. + 'T.custom18, '. + 'T.custom19, '. + 'T.custom20 '. + 'FROM '.$settings['db_pfix'].'tickets T '; + } } diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php index ebc97f47..abe7f05d 100644 --- a/web-services/ticket/index.php +++ b/web-services/ticket/index.php @@ -11,12 +11,14 @@ include('/../repositories/ticketRepository.php'); if(isset($_GET['id'])) { $ticket = TicketRepository::getTicketForId($_GET['id'], $hesk_settings); - //--A quick and dirty RESTful test using PHP. + echo json_encode($ticket); +} +elseif (isset($_GET['trackingid'])) +{ + $ticket = TicketRepository::getTicketForTrackingId($_GET['trackingid'], $hesk_settings); echo json_encode($ticket); } else { header(http_response_code(400)); } - -?> From a959e39881fc080ee7b6d1008df4dadd24b99a97 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 13 Jul 2014 11:22:38 -0400 Subject: [PATCH 13/52] renamed index.php to getTicket --- web-services/ticket/{index.php => getTicket.php} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename web-services/ticket/{index.php => getTicket.php} (100%) diff --git a/web-services/ticket/index.php b/web-services/ticket/getTicket.php similarity index 100% rename from web-services/ticket/index.php rename to web-services/ticket/getTicket.php From 1a502e7a1ebb8caf15c26295266b09be9212b564 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 22:05:40 -0500 Subject: [PATCH 14/52] Only allow getTicketById --- .../repositories/ticketRepository.php | 33 ++----------------- .../ticket/{getTicket.php => index.php} | 11 ++----- 2 files changed, 5 insertions(+), 39 deletions(-) rename web-services/ticket/{getTicket.php => index.php} (54%) diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php index 51368b7b..d77ea61c 100644 --- a/web-services/repositories/ticketRepository.php +++ b/web-services/repositories/ticketRepository.php @@ -1,6 +1,6 @@ connect_error) { return ('An error occurred when establishing a connection to the database.'); @@ -26,35 +26,6 @@ class TicketRepository { return self::generateTicketModel($result); } - public static function getTicketForTrackingId($id, $settings) - { - $connection = new mysqli($settings['db_host'], $settings['db_user'], $settings['db_pass'], $settings['db_name']); - if ($connection->connect_error) - { - return ('An error occurred when establishing a connection to the database.'); - } - - $sql = self::getDefaultSql($settings). - 'WHERE T.trackid = '.$id; - $results = $connection->query($sql); - - //-- There should only be one result as Tracking IDs should be unique. If there are two, return a 422 response. - if ($results->num_rows > 1) - { - header(http_response_code(422)); - return; - } elseif ($results->num_rows == 0) - { - //-- No ticket found. Return a 404. - header(http_response_code(404)); - return; - } else { - $result = $results->fetch_assoc(); - $connection->close(); - return self::generateTicketModel($result); - } - } - private static function generateTicketModel($result) { $ticket = new Ticket(); diff --git a/web-services/ticket/getTicket.php b/web-services/ticket/index.php similarity index 54% rename from web-services/ticket/getTicket.php rename to web-services/ticket/index.php index abe7f05d..2db108b1 100644 --- a/web-services/ticket/getTicket.php +++ b/web-services/ticket/index.php @@ -3,21 +3,16 @@ //-- This service will return ticket information for a specific ticket ID (NOT TRACKING ID) header('Content-Type: application/json'); define('IN_SCRIPT',1); -define('HESK_PATH','/../../'); +define('HESK_PATH','../../'); -require(HESK_PATH . 'hesk_settings.inc.php'); -include('/../repositories/ticketRepository.php'); +include(HESK_PATH . 'hesk_settings.inc.php'); +include(__DIR__ . '/../repositories/ticketRepository.php'); if(isset($_GET['id'])) { $ticket = TicketRepository::getTicketForId($_GET['id'], $hesk_settings); echo json_encode($ticket); } -elseif (isset($_GET['trackingid'])) -{ - $ticket = TicketRepository::getTicketForTrackingId($_GET['trackingid'], $hesk_settings); - echo json_encode($ticket); -} else { header(http_response_code(400)); From 9362a198eb4eca92f5bbd1ff91e350b4fe9fc112 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 15 Oct 2015 22:31:24 -0400 Subject: [PATCH 15/52] #365 Get started on api --- api/canned/index.php | 19 +++ api/core/database.inc.php | 247 ++++++++++++++++++++++++++++++ api/core/database_mysqli.inc.php | 253 +++++++++++++++++++++++++++++++ api/core/json_error.php | 11 ++ inc/common.inc.php | 13 ++ 5 files changed, 543 insertions(+) create mode 100644 api/canned/index.php create mode 100755 api/core/database.inc.php create mode 100755 api/core/database_mysqli.inc.php create mode 100644 api/core/json_error.php diff --git a/api/canned/index.php b/api/canned/index.php new file mode 100644 index 00000000..c9c35024 --- /dev/null +++ b/api/canned/index.php @@ -0,0 +1,19 @@ +EXPLAIN $query

    \n"; + + if ($res = @mysqli_query($hesk_db_link, $query)) + { + return $res; + } + elseif ($hesk_settings['debug_mode']) + { + $message = $hesklang['mysql_said'] . ': ' . mysqli_error($hesk_db_link); + } + else + { + $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; + } + print_error($hesklang['cant_sql'], $message); + die(http_response_code(500)); +} // END hesk_dbQuery() + + +function hesk_dbFetchAssoc($res) +{ + + return @mysqli_fetch_assoc($res); + +} // END hesk_FetchAssoc() + + +function hesk_dbFetchRow($res) +{ + + return @mysqli_fetch_row($res); + +} // END hesk_FetchRow() + + +function hesk_dbResult($res, $row = 0, $column = 0) +{ + $i=0; + $res->data_seek(0); + + while ($tmp = @mysqli_fetch_array($res, MYSQLI_NUM)) + { + if ($i==$row) + { + return $tmp[$column]; + } + $i++; + } + + return ''; + +} // END hesk_dbResult() + + +function hesk_dbInsertID() +{ + global $hesk_db_link; + + if ($lastid = @mysqli_insert_id($hesk_db_link)) + { + return $lastid; + } + +} // END hesk_dbInsertID() + + +function hesk_dbFreeResult($res) +{ + + return @mysqli_free_result($res); + +} // END hesk_dbFreeResult() + + +function hesk_dbNumRows($res) +{ + + return @mysqli_num_rows($res); + +} // END hesk_dbNumRows() + + +function hesk_dbAffectedRows() +{ + global $hesk_db_link; + + return @mysqli_affected_rows($hesk_db_link); + +} // END hesk_dbAffectedRows() diff --git a/api/core/json_error.php b/api/core/json_error.php new file mode 100644 index 00000000..61b491e6 --- /dev/null +++ b/api/core/json_error.php @@ -0,0 +1,11 @@ + $older_than) && @unlink($file)) ? true : false; From 0862b9376f600218defe9e00197d8f17d20d3f99 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 1 Nov 2015 11:58:14 -0500 Subject: [PATCH 16/52] Add application/json headers for errors --- api/core/database.inc.php | 3 +++ api/core/database_mysqli.inc.php | 2 ++ 2 files changed, 5 insertions(+) diff --git a/api/core/database.inc.php b/api/core/database.inc.php index 1bcee815..c8d98d34 100755 --- a/api/core/database.inc.php +++ b/api/core/database.inc.php @@ -120,6 +120,7 @@ function hesk_dbConnect() { $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; } + header('Content-Type: application/json'); print_error($hesklang['cant_connect_db'], $message); return http_response_code(500); } @@ -134,6 +135,7 @@ function hesk_dbConnect() { $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; } + header('Content-Type: application/json'); print_error($hesklang['cant_connect_db'], $message); die(); } @@ -180,6 +182,7 @@ function hesk_dbQuery($query) { $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; } + header('Content-Type: application/json'); print_error($hesklang['cant_sql'], $message); die(); diff --git a/api/core/database_mysqli.inc.php b/api/core/database_mysqli.inc.php index f2569261..fc13df26 100755 --- a/api/core/database_mysqli.inc.php +++ b/api/core/database_mysqli.inc.php @@ -128,6 +128,7 @@ function hesk_dbConnect() { $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; } + header('Content-Type: application/json'); print_error($hesklang['cant_connect_db'], $message); http_response_code(500); } @@ -176,6 +177,7 @@ function hesk_dbQuery($query) { $message = $hesklang['contact_webmaster'] . $hesk_settings['webmaster_email']; } + header('Content-Type: application/json'); print_error($hesklang['cant_sql'], $message); die(http_response_code(500)); } // END hesk_dbQuery() From 8985413901db0cd1fe51521a8b3ced5a8d62468f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 1 Nov 2015 11:58:30 -0500 Subject: [PATCH 17/52] #407 Add endpoint for canned responses --- api/canned/index.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/canned/index.php b/api/canned/index.php index c9c35024..996f6274 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -9,9 +9,10 @@ hesk_dbConnect(); // Routing if (isset($_GET['id'])) { - $response = hesk_dbQuery("SELECT `id`, `message`, `html`, `title`, `reply_order` FROM `" + $response = hesk_dbQuery("SELECT `id`, `message`, `title`, `reply_order` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` WHERE `id` = ".intval($_GET['id'])); $result = hesk_dbFetchAssoc($response); + $result['message'] = html_entity_decode($result['message']); header('Content-Type: application/json'); print json_encode($result); From 99193274dfb9bd995fc872844c63754e79e667be Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 1 Nov 2015 14:17:02 -0500 Subject: [PATCH 18/52] Add ticket templates, make some tweaks to canned endpoint --- api/canned/index.php | 6 +++++- api/ticket-templates/index.php | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 api/ticket-templates/index.php diff --git a/api/canned/index.php b/api/canned/index.php index 996f6274..cd0b5387 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -11,8 +11,12 @@ hesk_dbConnect(); if (isset($_GET['id'])) { $response = hesk_dbQuery("SELECT `id`, `message`, `title`, `reply_order` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` WHERE `id` = ".intval($_GET['id'])); + if (hesk_dbNumRows($response) == 0) { + return http_response_code(404); + } $result = hesk_dbFetchAssoc($response); - $result['message'] = html_entity_decode($result['message']); + $result['title'] = hesk_html_entity_decode($result['title']); + $result['message'] = hesk_html_entity_decode($result['message']); header('Content-Type: application/json'); print json_encode($result); diff --git a/api/ticket-templates/index.php b/api/ticket-templates/index.php new file mode 100644 index 00000000..c2e02b79 --- /dev/null +++ b/api/ticket-templates/index.php @@ -0,0 +1,24 @@ + Date: Sun, 1 Nov 2015 14:20:19 -0500 Subject: [PATCH 19/52] Allow retrieval of all canned responses / ticket tpls --- api/canned/index.php | 14 +++++++++++++- api/ticket-templates/index.php | 14 +++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/api/canned/index.php b/api/canned/index.php index cd0b5387..b8fc9fb6 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -21,4 +21,16 @@ if (isset($_GET['id'])) { header('Content-Type: application/json'); print json_encode($result); return http_response_code(200); -} \ No newline at end of file +} + +$response = hesk_dbQuery("SELECT `id`, `message`, `title`, `reply_order` FROM `" + . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies`"); +$results = []; +while ($row = hesk_dbFetchAssoc($response)) { + $row['title'] = hesk_html_entity_decode($row['title']); + $row['message'] = hesk_html_entity_decode($row['message']); + $results[] = $row; +} +header('Content-Type: application/json'); +print json_encode($results); +return http_response_code(200); \ No newline at end of file diff --git a/api/ticket-templates/index.php b/api/ticket-templates/index.php index c2e02b79..5b718598 100644 --- a/api/ticket-templates/index.php +++ b/api/ticket-templates/index.php @@ -21,4 +21,16 @@ if (isset($_GET['id'])) { header('Content-Type: application/json'); print json_encode($result); return http_response_code(200); -} \ No newline at end of file +} + +$response = hesk_dbQuery("SELECT `id`, `message`, `title`, `tpl_order` FROM `" + . hesk_dbEscape($hesk_settings['db_pfix']) . "ticket_templates`"); +$results = []; +while ($row = hesk_dbFetchAssoc($response)) { + $row['title'] = hesk_html_entity_decode($row['title']); + $row['message'] = hesk_html_entity_decode($row['message']); + $results[] = $row; +} +header('Content-Type: application/json'); +print json_encode($results); +return http_response_code(200); \ No newline at end of file From 6150f113c94d3fa2fddfac83308e79423bbea592 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 1 Nov 2015 14:41:06 -0500 Subject: [PATCH 20/52] Rename folder --- api/{ticket-templates => ticket-template}/index.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename api/{ticket-templates => ticket-template}/index.php (100%) diff --git a/api/ticket-templates/index.php b/api/ticket-template/index.php similarity index 100% rename from api/ticket-templates/index.php rename to api/ticket-template/index.php From e4763b3e0b9cfb7c1c2f8a69ece2b659b5651a63 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 1 Nov 2015 22:08:27 -0500 Subject: [PATCH 21/52] Use output function to handle headers and json encoding --- api/canned/index.php | 6 +++--- api/core/output.php | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 api/core/output.php diff --git a/api/canned/index.php b/api/canned/index.php index b8fc9fb6..810dec85 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -1,8 +1,10 @@ Date: Mon, 2 Nov 2015 12:45:34 -0500 Subject: [PATCH 22/52] Some extraction of code into DAOs --- api/canned/index.php | 34 ++++++++++------------------ api/dao/canned_dao.php | 23 +++++++++++++++++++ api/dao/ticket_template_dao.php | 23 +++++++++++++++++++ api/ticket-template/index.php | 39 ++++++++++++--------------------- 4 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 api/dao/canned_dao.php create mode 100644 api/dao/ticket_template_dao.php diff --git a/api/canned/index.php b/api/canned/index.php index 810dec85..7a713696 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -5,32 +5,20 @@ define('API_PATH', '../'); require(HESK_PATH . 'hesk_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); require(API_PATH . 'core/output.php'); +require(API_PATH . 'dao/canned_dao.php'); hesk_load_api_database_functions(); hesk_dbConnect(); // Routing -if (isset($_GET['id'])) { - $response = hesk_dbQuery("SELECT `id`, `message`, `title`, `reply_order` FROM `" - . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies` WHERE `id` = ".intval($_GET['id'])); - if (hesk_dbNumRows($response) == 0) { - return http_response_code(404); +$request_method = $_SERVER['REQUEST_METHOD']; +if ($request_method == 'GET') { + if (isset($_GET['id'])) { + $results = get_canned_response($hesk_settings, $_GET['id']); + } else { + $results = get_canned_response($hesk_settings); } - $result = hesk_dbFetchAssoc($response); - $result['title'] = hesk_html_entity_decode($result['title']); - $result['message'] = hesk_html_entity_decode($result['message']); - - output($result); -} - -$response = hesk_dbQuery("SELECT `id`, `message`, `title`, `reply_order` FROM `" - . hesk_dbEscape($hesk_settings['db_pfix']) . "std_replies`"); -$results = []; -while ($row = hesk_dbFetchAssoc($response)) { - $row['title'] = hesk_html_entity_decode($row['title']); - $row['message'] = hesk_html_entity_decode($row['message']); - $results[] = $row; -} -header('Content-Type: application/json'); -print json_encode($results); -return http_response_code(200); \ No newline at end of file + output($results); +} else { + return http_response_code(405); +} \ No newline at end of file diff --git a/api/dao/canned_dao.php b/api/dao/canned_dao.php new file mode 100644 index 00000000..37f17aaa --- /dev/null +++ b/api/dao/canned_dao.php @@ -0,0 +1,23 @@ + Date: Mon, 2 Nov 2015 12:48:59 -0500 Subject: [PATCH 23/52] Everything is only needed once --- api/canned/index.php | 8 ++++---- api/ticket-template/index.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/canned/index.php b/api/canned/index.php index 7a713696..e1e8de31 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -2,10 +2,10 @@ define('IN_SCRIPT', 1); define('HESK_PATH', '../../'); define('API_PATH', '../'); -require(HESK_PATH . 'hesk_settings.inc.php'); -require(HESK_PATH . 'inc/common.inc.php'); -require(API_PATH . 'core/output.php'); -require(API_PATH . 'dao/canned_dao.php'); +require_once(HESK_PATH . 'hesk_settings.inc.php'); +require_once(HESK_PATH . 'inc/common.inc.php'); +require_once(API_PATH . 'core/output.php'); +require_once(API_PATH . 'dao/canned_dao.php'); hesk_load_api_database_functions(); hesk_dbConnect(); diff --git a/api/ticket-template/index.php b/api/ticket-template/index.php index 7300d3a7..7f79c172 100644 --- a/api/ticket-template/index.php +++ b/api/ticket-template/index.php @@ -2,10 +2,10 @@ define('IN_SCRIPT', 1); define('HESK_PATH', '../../'); define('API_PATH', '../'); -require(HESK_PATH . 'hesk_settings.inc.php'); -require(HESK_PATH . 'inc/common.inc.php'); -require(API_PATH . 'core/output.php'); -require(API_PATH . 'dao/ticket_template_dao.php'); +require_once(HESK_PATH . 'hesk_settings.inc.php'); +require_once(HESK_PATH . 'inc/common.inc.php'); +require_once(API_PATH . 'core/output.php'); +require_once(API_PATH . 'dao/ticket_template_dao.php'); hesk_load_api_database_functions(); hesk_dbConnect(); From 490dcdb76402c2ebe2d366aa8b43e50daa6c997a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 2 Nov 2015 12:55:32 -0500 Subject: [PATCH 24/52] Ticket API and return 404 if no results --- api/canned/index.php | 4 + api/dao/ticket_dao.php | 21 +++ api/ticket-template/index.php | 4 + api/ticket/index.php | 28 ++++ web-services/models/ticket.php | 51 ------- .../repositories/ticketRepository.php | 144 ------------------ web-services/ticket/index.php | 19 --- 7 files changed, 57 insertions(+), 214 deletions(-) create mode 100644 api/dao/ticket_dao.php create mode 100644 api/ticket/index.php delete mode 100644 web-services/models/ticket.php delete mode 100644 web-services/repositories/ticketRepository.php delete mode 100644 web-services/ticket/index.php diff --git a/api/canned/index.php b/api/canned/index.php index e1e8de31..0dd2548c 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -18,6 +18,10 @@ if ($request_method == 'GET') { } else { $results = get_canned_response($hesk_settings); } + + if ($results == NULL) { + return http_response_code(404); + } output($results); } else { return http_response_code(405); diff --git a/api/dao/ticket_dao.php b/api/dao/ticket_dao.php new file mode 100644 index 00000000..ddd85c7b --- /dev/null +++ b/api/dao/ticket_dao.php @@ -0,0 +1,21 @@ + diff --git a/web-services/repositories/ticketRepository.php b/web-services/repositories/ticketRepository.php deleted file mode 100644 index d77ea61c..00000000 --- a/web-services/repositories/ticketRepository.php +++ /dev/null @@ -1,144 +0,0 @@ -connect_error) - { - return ('An error occurred when establishing a connection to the database.'); - } - - $sql = self::getDefaultSql($settings). - 'WHERE T.id = '.$id; - $results = $connection->query($sql); - - //-- There will only ever be one result, as ID is the primary key on the tickets table. - $result = $results->fetch_assoc(); - $connection->close(); - return self::generateTicketModel($result); - } - - private static function generateTicketModel($result) { - $ticket = new Ticket(); - - settype($result['id'], 'int'); - $ticket->id = $result['id']; - - $ticket->trackingId = $result['trackid']; - $ticket->name = $result['ContactName']; - $ticket->email = $result['email']; - - settype($result['category'], 'int'); - $ticket->category = $result['category']; - - settype($result['priority'], 'int'); - $ticket->priority = $result['priority']; - - $ticket->subject = $result['subject']; - $ticket->message = $result['message']; - - //-- Convert these to times so the receiver can use whatever format they want to display the date/time without extra work. - $ticket->dateCreated = strtotime($result['dt']); - $ticket->dateModified = strtotime($result['lastchange']); - $ticket->ip = $result['ip']; - $ticket->language = $result['language']; - - settype($result['status'], 'int'); - $ticket->status = $result['status']; - - settype($result['owner'], 'int'); - $ticket->owner = $result['owner']; - - $ticket->timeWorked = $result['time_worked']; - - settype($result['lastreplier'], 'int'); - $ticket->lastReplier = $result['lastreplier']; - - settype($result['replierid'], 'int'); - $ticket->replierId = $result['replierid']; - $ticket->isArchived = ($result['archive'] ? true : false); - $ticket->isLocked = ($result['locked'] ? true : false); - $ticket->attachments = $result['attachments']; - - //-- explode handles splitting the list into an array, array_filter removes the empty string elements (""), and array_values resets the indicies. - $ticket->merged = array_values(array_filter(explode('#',$result['merged']))); - - //-- Not currently returning history, as it can contain a metric shit-ton of HTML code and will cludder up the JSON response. - //$ticket->history = $result['history']; - $ticket->custom1 = $result['custom1'] == '' ? null : $result['custom1']; - $ticket->custom2 = $result['custom2'] == '' ? null : $result['custom2']; - $ticket->custom3 = $result['custom3'] == '' ? null : $result['custom3']; - $ticket->custom4 = $result['custom4'] == '' ? null : $result['custom4']; - $ticket->custom5 = $result['custom5'] == '' ? null : $result['custom5']; - $ticket->custom6 = $result['custom6'] == '' ? null : $result['custom6']; - $ticket->custom7 = $result['custom7'] == '' ? null : $result['custom7']; - $ticket->custom8 = $result['custom8'] == '' ? null : $result['custom8']; - $ticket->custom9 = $result['custom9'] == '' ? null : $result['custom9']; - $ticket->custom10 = $result['custom10'] == '' ? null : $result['custom10']; - $ticket->custom11 = $result['custom11'] == '' ? null : $result['custom11']; - $ticket->custom12 = $result['custom12'] == '' ? null : $result['custom12']; - $ticket->custom13 = $result['custom13'] == '' ? null : $result['custom13']; - $ticket->custom14 = $result['custom14'] == '' ? null : $result['custom14']; - $ticket->custom15 = $result['custom15'] == '' ? null : $result['custom15']; - $ticket->custom16 = $result['custom16'] == '' ? null : $result['custom16']; - $ticket->custom17 = $result['custom17'] == '' ? null : $result['custom17']; - $ticket->custom18 = $result['custom18'] == '' ? null : $result['custom18']; - $ticket->custom19 = $result['custom19'] == '' ? null : $result['custom19']; - $ticket->custom20 = $result['custom20'] == '' ? null : $result['custom20']; - - return $ticket; - } - - private function getDefaultSql($settings) { - return 'SELECT T.id, '. - 'T.trackid, '. - 'T.name AS "ContactName", '. - 'T.email, '. - 'T.category, '. - 'T.priority, '. - 'T.subject, '. - 'T.message, '. - 'T.dt, '. - 'T.lastchange, '. - 'T.ip, '. - 'T.language, '. - 'T.status, '. - 'T.owner, '. - 'T.time_worked, '. - 'T.lastreplier, '. - 'T.replierid, '. - 'T.archive, '. - 'T.locked, '. - 'T.attachments, '. - 'T.merged, '. - 'T.custom1, '. - 'T.custom2, '. - 'T.custom3, '. - 'T.custom4, '. - 'T.custom5, '. - 'T.custom6, '. - 'T.custom7, '. - 'T.custom8, '. - 'T.custom9, '. - 'T.custom10, '. - 'T.custom11, '. - 'T.custom12, '. - 'T.custom13, '. - 'T.custom14, '. - 'T.custom15, '. - 'T.custom16, '. - 'T.custom17, '. - 'T.custom18, '. - 'T.custom19, '. - 'T.custom20 '. - 'FROM '.$settings['db_pfix'].'tickets T '; - } -} diff --git a/web-services/ticket/index.php b/web-services/ticket/index.php deleted file mode 100644 index 2db108b1..00000000 --- a/web-services/ticket/index.php +++ /dev/null @@ -1,19 +0,0 @@ - Date: Mon, 2 Nov 2015 13:00:34 -0500 Subject: [PATCH 25/52] Remove unnecessary else block --- api/canned/index.php | 6 +++--- api/ticket-template/index.php | 8 ++++---- api/ticket/index.php | 8 ++++---- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/api/canned/index.php b/api/canned/index.php index 0dd2548c..e93c58cd 100644 --- a/api/canned/index.php +++ b/api/canned/index.php @@ -23,6 +23,6 @@ if ($request_method == 'GET') { return http_response_code(404); } output($results); -} else { - return http_response_code(405); -} \ No newline at end of file +} + +return http_response_code(405); \ No newline at end of file diff --git a/api/ticket-template/index.php b/api/ticket-template/index.php index e3d06eda..8335810e 100644 --- a/api/ticket-template/index.php +++ b/api/ticket-template/index.php @@ -23,7 +23,7 @@ if ($request_method == 'GET') { if ($results == NULL) { return http_response_code(404); } - output($results); -} else { - return http_response_code(405); -} \ No newline at end of file + return output($results); +} + +return http_response_code(405); \ No newline at end of file diff --git a/api/ticket/index.php b/api/ticket/index.php index 165f6397..f111e646 100644 --- a/api/ticket/index.php +++ b/api/ticket/index.php @@ -22,7 +22,7 @@ if ($request_method == 'GET') { if ($results == NULL) { return http_response_code(404); } - output($results); -} else { - return http_response_code(405); -} \ No newline at end of file + return output($results); +} + +return http_response_code(405); \ No newline at end of file From b6a6a4186b59597976499a027c0d13afba599a43 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 2 Nov 2015 22:13:37 -0500 Subject: [PATCH 26/52] Relocate some APIs, start on category API --- api/{ => admin}/canned/index.php | 4 ++-- api/admin/category/index.php | 29 +++++++++++++++++++++++ api/{ => admin}/ticket-template/index.php | 4 ++-- api/{ => admin}/ticket/index.php | 4 ++-- api/dao/category_dao.php | 5 ++++ 5 files changed, 40 insertions(+), 6 deletions(-) rename api/{ => admin}/canned/index.php (87%) create mode 100644 api/admin/category/index.php rename api/{ => admin}/ticket-template/index.php (87%) rename api/{ => admin}/ticket/index.php (87%) create mode 100644 api/dao/category_dao.php diff --git a/api/canned/index.php b/api/admin/canned/index.php similarity index 87% rename from api/canned/index.php rename to api/admin/canned/index.php index e93c58cd..39312959 100644 --- a/api/canned/index.php +++ b/api/admin/canned/index.php @@ -1,7 +1,7 @@ Date: Thu, 5 Nov 2015 21:55:23 -0500 Subject: [PATCH 27/52] #412 Add /admin/category --- api/dao/category_dao.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/api/dao/category_dao.php b/api/dao/category_dao.php index 49e9bea4..895b141c 100644 --- a/api/dao/category_dao.php +++ b/api/dao/category_dao.php @@ -1,5 +1,27 @@ Date: Thu, 5 Nov 2015 22:01:14 -0500 Subject: [PATCH 28/52] Improve ticket API --- api/dao/ticket_dao.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/api/dao/ticket_dao.php b/api/dao/ticket_dao.php index ddd85c7b..84ee0ca4 100644 --- a/api/dao/ticket_dao.php +++ b/api/dao/ticket_dao.php @@ -14,6 +14,23 @@ function get_ticket_for_id($hesk_settings, $id = NULL) { $results = []; while ($row = hesk_dbFetchAssoc($response)) { + $row['id'] = intval($row['id']); + $row['category'] = intval($row['category']); + $row['priority'] = intval($row['priority']); + $row['status'] = intval($row['status']); + $row['openedby'] = intval($row['openedby']); + $row['lastreplier'] = intval($row['lastreplier']); + $row['replierid'] = intval($row['replierid']); + $row['archive'] = $row['archive'] == true; + $row['locked'] = $row['locked'] == true; + $row['html'] = $row['html'] == true; + $row['screen_resolution_height'] = $row['screen_resolution_height'] != NULL + ? intval($row['screen_resolution_height']) + : NULL; + $row['screen_resolution_width'] = $row['screen_resolution_width'] != NULL + ? intval($row['screen_resolution_width']) + : NULL; + $results[] = $row; } From 3129adda881621ef81752e1e9b3aad197854c12c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 5 Nov 2015 22:02:07 -0500 Subject: [PATCH 29/52] Improve ticket template API --- api/dao/ticket_template_dao.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/dao/ticket_template_dao.php b/api/dao/ticket_template_dao.php index 43f45e85..d31d8aa4 100644 --- a/api/dao/ticket_template_dao.php +++ b/api/dao/ticket_template_dao.php @@ -14,6 +14,8 @@ function get_ticket_template($hesk_settings, $id = NULL) { $results = []; while ($row = hesk_dbFetchAssoc($response)) { + $row['id'] = intval($row['id']); + $row['tpl_order'] = intval($row['tpl_order']); $row['title'] = hesk_html_entity_decode($row['title']); $row['message'] = hesk_html_entity_decode($row['message']); $results[] = $row; From 40d8b2b4a47e8af57847eb4a4e50ec9c8f132642 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 5 Nov 2015 22:02:49 -0500 Subject: [PATCH 30/52] Improve canned responses API --- api/dao/canned_dao.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/dao/canned_dao.php b/api/dao/canned_dao.php index 37f17aaa..ea653942 100644 --- a/api/dao/canned_dao.php +++ b/api/dao/canned_dao.php @@ -14,6 +14,8 @@ function get_canned_response($hesk_settings, $id = NULL) { $results = []; while ($row = hesk_dbFetchAssoc($response)) { + $row['id'] = intval($row['id']); + $row['reply_order'] = intval($row['reply_order']); $row['title'] = hesk_html_entity_decode($row['title']); $row['message'] = hesk_html_entity_decode($row['message']); $results[] = $row; From 0a3d50009ae8f16a48f4d8059d2b72ee15bf2237 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 6 Nov 2015 21:55:06 -0500 Subject: [PATCH 31/52] Add get ticket by tracking ID --- api/admin/ticket/index.php | 2 ++ api/dao/ticket_dao.php | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/api/admin/ticket/index.php b/api/admin/ticket/index.php index 2afd98bb..c153457b 100644 --- a/api/admin/ticket/index.php +++ b/api/admin/ticket/index.php @@ -15,6 +15,8 @@ $request_method = $_SERVER['REQUEST_METHOD']; if ($request_method == 'GET') { if (isset($_GET['id'])) { $results = get_ticket_for_id($hesk_settings, $_GET['id']); + } elseif (isset($_GET['trackid'])) { + $results = get_ticket_by_tracking_id($hesk_settings, $_GET['trackid']); } else { $results = get_ticket_for_id($hesk_settings); } diff --git a/api/dao/ticket_dao.php b/api/dao/ticket_dao.php index 84ee0ca4..739fff38 100644 --- a/api/dao/ticket_dao.php +++ b/api/dao/ticket_dao.php @@ -12,6 +12,12 @@ function get_ticket_for_id($hesk_settings, $id = NULL) { return NULL; } + $results = build_results($response); + + return $id == NULL ? $results : $results[0]; +} + +function build_results($response) { $results = []; while ($row = hesk_dbFetchAssoc($response)) { $row['id'] = intval($row['id']); @@ -34,5 +40,19 @@ function get_ticket_for_id($hesk_settings, $id = NULL) { $results[] = $row; } - return $id == NULL ? $results : $results[0]; + return $results; +} + +function get_ticket_by_tracking_id($hesk_settings, $trackid) { + $sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" + . hesk_dbEscape($trackid) . "'"; + + $response = hesk_dbQuery($sql); + + if (hesk_dbNumRows($response) == 0) { + return NULL; + } + + $results = build_results($response); + return $results[0]; } \ No newline at end of file From 4fa94bec1a8ed610bb8499283530737529cbd895 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 6 Nov 2015 22:23:28 -0500 Subject: [PATCH 32/52] Add status API --- api/dao/status_dao.php | 52 ++++++++++++++++++++++++++++++++++++++++++ api/status/index.php | 29 +++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 api/dao/status_dao.php create mode 100644 api/status/index.php diff --git a/api/dao/status_dao.php b/api/dao/status_dao.php new file mode 100644 index 00000000..fba8b4ba --- /dev/null +++ b/api/dao/status_dao.php @@ -0,0 +1,52 @@ + $value) { + if ($key != 'id') { + $lowercase_key = lcfirst($key); + $row[$lowercase_key] = $row[$key]; + unset($row[$key]); + } + if ($key == 'id' || $lowercase_key == 'closable' + || $lowercase_key == 'key' || $lowercase_key == 'sort' + || $lowercase_key == 'textColor') { + continue; + } + $row[$lowercase_key] = $row[$lowercase_key] == true; + } + + $language_sql = "SELECT * FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "text_to_status_xref` " + . "WHERE `status_id` = ".intval($row['id']); + + $language_rs = hesk_dbQuery($language_sql); + if (hesk_dbNumRows($language_rs) > 0) { + $row['key'] = NULL; + $row['keys'] = []; + } + while ($language_row = hesk_dbFetchAssoc($language_rs)) { + unset($language_row['id']); + unset($language_row['status_id']); + $row['keys'][] = $language_row; + } + + $results[] = $row; + } + + return $id == NULL ? $results : $results[0]; +} \ No newline at end of file diff --git a/api/status/index.php b/api/status/index.php new file mode 100644 index 00000000..e6727d84 --- /dev/null +++ b/api/status/index.php @@ -0,0 +1,29 @@ + Date: Mon, 16 Nov 2015 22:18:38 -0500 Subject: [PATCH 33/52] #414 Start working on the API settings page --- admin/api_settings.php | 129 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 admin/api_settings.php diff --git a/admin/api_settings.php b/admin/api_settings.php new file mode 100644 index 00000000..edd7c504 --- /dev/null +++ b/admin/api_settings.php @@ -0,0 +1,129 @@ +install folder from your server for security reasons then refresh this page!'); +} + +// Get all the required files and functions +require(HESK_PATH . 'hesk_settings.inc.php'); + +// Save the default language for the settings page before choosing user's preferred one +$hesk_settings['language_default'] = $hesk_settings['language']; +require(HESK_PATH . 'inc/common.inc.php'); +$hesk_settings['language'] = $hesk_settings['language_default']; +require(HESK_PATH . 'inc/admin_functions.inc.php'); +hesk_load_database_functions(); + +hesk_session_start(); +hesk_dbConnect(); +hesk_isLoggedIn(); + +// Check permissions for this feature +hesk_checkPermission('can_man_settings'); + +// Print header +require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); + +// Print main manage users page +require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); +?> + +
    +
    +
    +
    + API Information +
    + + + + + + + + + +
    + API Version + + +
    + External API + + Enabled +
    +
    +
    +
    +

    API Settings

    +
    + +
    +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    +

    User Security Stuff here (tokens, etc)

    +
    +
    +
    + + Date: Tue, 17 Nov 2015 21:27:57 -0500 Subject: [PATCH 34/52] Can now enable/disable public API --- admin/api_settings.php | 39 +++- css/mods-for-hesk.css | 4 - inc/common.inc.php | 12 + inc/headerAdmin.inc.php | 6 + install/mods-for-hesk/sql/installSql.php | 10 + internal-api/admin/api-settings/index.php | 28 +++ internal-api/core/database.inc.php | 250 +++++++++++++++++++++ internal-api/core/database_mysqli.inc.php | 255 ++++++++++++++++++++++ internal-api/core/json_error.php | 11 + internal-api/core/output.php | 7 + internal-api/dao/settings_dao.php | 8 + internal-api/js/api-settings.js | 52 +++++ internal-api/js/core.php | 9 + 13 files changed, 676 insertions(+), 15 deletions(-) create mode 100644 internal-api/admin/api-settings/index.php create mode 100755 internal-api/core/database.inc.php create mode 100755 internal-api/core/database_mysqli.inc.php create mode 100644 internal-api/core/json_error.php create mode 100644 internal-api/core/output.php create mode 100644 internal-api/dao/settings_dao.php create mode 100644 internal-api/js/api-settings.js create mode 100644 internal-api/js/core.php diff --git a/admin/api_settings.php b/admin/api_settings.php index edd7c504..6cb8b676 100644 --- a/admin/api_settings.php +++ b/admin/api_settings.php @@ -39,11 +39,7 @@ if (is_dir(HESK_PATH . 'install')) { // Get all the required files and functions require(HESK_PATH . 'hesk_settings.inc.php'); - -// Save the default language for the settings page before choosing user's preferred one -$hesk_settings['language_default'] = $hesk_settings['language']; require(HESK_PATH . 'inc/common.inc.php'); -$hesk_settings['language'] = $hesk_settings['language_default']; require(HESK_PATH . 'inc/admin_functions.inc.php'); hesk_load_database_functions(); @@ -54,9 +50,13 @@ hesk_isLoggedIn(); // Check permissions for this feature hesk_checkPermission('can_man_settings'); +$modsForHesk_settings = mfh_getSettings(); + +define('EXTRA_JS', ''); // Print header require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); + // Print main manage users page require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> @@ -80,8 +80,13 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); External API - - Enabled + + + Disabled + Enabled @@ -93,7 +98,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    @@ -106,14 +111,26 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); data-content="Enable or Disable the Public REST API.">
    -
    -
    + + + + + +
    diff --git a/css/mods-for-hesk.css b/css/mods-for-hesk.css index 8e62d840..fa9537dc 100644 --- a/css/mods-for-hesk.css +++ b/css/mods-for-hesk.css @@ -197,10 +197,6 @@ div.setupButtons { padding: 10px 0; } -.hide { - display: none; -} - .font-size-90 { font-size: .9em !important; } diff --git a/inc/common.inc.php b/inc/common.inc.php index 963fe2f2..2e4d4cbe 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -167,6 +167,18 @@ function hesk_load_api_database_functions() } // END hesk_load_database_functions() +function hesk_load_internal_api_database_functions() +{ + require(HESK_PATH . 'internal-api/core/json_error.php'); + // Preferrably use the MySQLi functions + if (function_exists('mysqli_connect')) { + require(HESK_PATH . 'internal-api/core/database_mysqli.inc.php'); + } // Default to MySQL + else { + require(HESK_PATH . 'internal-api/core/database.inc.php'); + } +} // END hesk_load_database_functions() + function hesk_unlink($file, $older_than = 0) { return (is_file($file) && (!$older_than || (time() - filectime($file)) > $older_than) && @unlink($file)) ? true : false; diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index f1504330..35698c70 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -89,6 +89,12 @@ $modsForHesk_settings = mfh_getSettings(); + +