diff --git a/.gitignore b/.gitignore index 70d3d8c3..ad0887cb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ admin/archive.php admin/custom_statuses.php admin/email_templates.php admin/generate_spam_question.php -admin/priority.php admin/test_connection.php attachments/index.htm cache/ @@ -198,52 +197,52 @@ inc/tabs/tabber-minimized.js inc/tabs/tabber.css inc/timer/hesk_timer.js inc/timer/index.htm -inc/tiny_mce/3.5.11/langs/en.js -inc/tiny_mce/3.5.11/license.txt -inc/tiny_mce/3.5.11/themes/advanced/about.htm -inc/tiny_mce/3.5.11/themes/advanced/anchor.htm -inc/tiny_mce/3.5.11/themes/advanced/charmap.htm -inc/tiny_mce/3.5.11/themes/advanced/color_picker.htm -inc/tiny_mce/3.5.11/themes/advanced/editor_template.js -inc/tiny_mce/3.5.11/themes/advanced/image.htm -inc/tiny_mce/3.5.11/themes/advanced/img/colorpicker.jpg -inc/tiny_mce/3.5.11/themes/advanced/img/flash.gif -inc/tiny_mce/3.5.11/themes/advanced/img/icons.gif -inc/tiny_mce/3.5.11/themes/advanced/img/iframe.gif -inc/tiny_mce/3.5.11/themes/advanced/img/pagebreak.gif -inc/tiny_mce/3.5.11/themes/advanced/img/quicktime.gif -inc/tiny_mce/3.5.11/themes/advanced/img/realmedia.gif -inc/tiny_mce/3.5.11/themes/advanced/img/shockwave.gif -inc/tiny_mce/3.5.11/themes/advanced/img/trans.gif -inc/tiny_mce/3.5.11/themes/advanced/img/video.gif -inc/tiny_mce/3.5.11/themes/advanced/img/windowsmedia.gif -inc/tiny_mce/3.5.11/themes/advanced/js/about.js -inc/tiny_mce/3.5.11/themes/advanced/js/anchor.js -inc/tiny_mce/3.5.11/themes/advanced/js/charmap.js -inc/tiny_mce/3.5.11/themes/advanced/js/color_picker.js -inc/tiny_mce/3.5.11/themes/advanced/js/image.js -inc/tiny_mce/3.5.11/themes/advanced/js/link.js -inc/tiny_mce/3.5.11/themes/advanced/js/source_editor.js -inc/tiny_mce/3.5.11/themes/advanced/langs/en.js -inc/tiny_mce/3.5.11/themes/advanced/langs/en_dlg.js -inc/tiny_mce/3.5.11/themes/advanced/link.htm -inc/tiny_mce/3.5.11/themes/advanced/shortcuts.htm -inc/tiny_mce/3.5.11/themes/advanced/skins/default/content.css -inc/tiny_mce/3.5.11/themes/advanced/skins/default/dialog.css -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/buttons.png -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/items.gif -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/menu_arrow.gif -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/menu_check.gif -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/progress.gif -inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/tabs.gif -inc/tiny_mce/3.5.11/themes/advanced/skins/default/ui.css -inc/tiny_mce/3.5.11/themes/advanced/source_editor.htm -inc/tiny_mce/3.5.11/tiny_mce.js -inc/tiny_mce/3.5.11/tiny_mce_popup.js -inc/tiny_mce/3.5.11/utils/editable_selects.js -inc/tiny_mce/3.5.11/utils/form_utils.js -inc/tiny_mce/3.5.11/utils/mctabs.js -inc/tiny_mce/3.5.11/utils/validate.js +inc/tiny_mce/3.5.12/langs/en.js +inc/tiny_mce/3.5.12/license.txt +inc/tiny_mce/3.5.12/themes/advanced/about.htm +inc/tiny_mce/3.5.12/themes/advanced/anchor.htm +inc/tiny_mce/3.5.12/themes/advanced/charmap.htm +inc/tiny_mce/3.5.12/themes/advanced/color_picker.htm +inc/tiny_mce/3.5.12/themes/advanced/editor_template.js +inc/tiny_mce/3.5.12/themes/advanced/image.htm +inc/tiny_mce/3.5.12/themes/advanced/img/colorpicker.jpg +inc/tiny_mce/3.5.12/themes/advanced/img/flash.gif +inc/tiny_mce/3.5.12/themes/advanced/img/icons.gif +inc/tiny_mce/3.5.12/themes/advanced/img/iframe.gif +inc/tiny_mce/3.5.12/themes/advanced/img/pagebreak.gif +inc/tiny_mce/3.5.12/themes/advanced/img/quicktime.gif +inc/tiny_mce/3.5.12/themes/advanced/img/realmedia.gif +inc/tiny_mce/3.5.12/themes/advanced/img/shockwave.gif +inc/tiny_mce/3.5.12/themes/advanced/img/trans.gif +inc/tiny_mce/3.5.12/themes/advanced/img/video.gif +inc/tiny_mce/3.5.12/themes/advanced/img/windowsmedia.gif +inc/tiny_mce/3.5.12/themes/advanced/js/about.js +inc/tiny_mce/3.5.12/themes/advanced/js/anchor.js +inc/tiny_mce/3.5.12/themes/advanced/js/charmap.js +inc/tiny_mce/3.5.12/themes/advanced/js/color_picker.js +inc/tiny_mce/3.5.12/themes/advanced/js/image.js +inc/tiny_mce/3.5.12/themes/advanced/js/link.js +inc/tiny_mce/3.5.12/themes/advanced/js/source_editor.js +inc/tiny_mce/3.5.12/themes/advanced/langs/en.js +inc/tiny_mce/3.5.12/themes/advanced/langs/en_dlg.js +inc/tiny_mce/3.5.12/themes/advanced/link.htm +inc/tiny_mce/3.5.12/themes/advanced/shortcuts.htm +inc/tiny_mce/3.5.12/themes/advanced/skins/default/content.css +inc/tiny_mce/3.5.12/themes/advanced/skins/default/dialog.css +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/buttons.png +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/items.gif +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/menu_arrow.gif +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/menu_check.gif +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/progress.gif +inc/tiny_mce/3.5.12/themes/advanced/skins/default/img/tabs.gif +inc/tiny_mce/3.5.12/themes/advanced/skins/default/ui.css +inc/tiny_mce/3.5.12/themes/advanced/source_editor.htm +inc/tiny_mce/3.5.12/tiny_mce.js +inc/tiny_mce/3.5.12/tiny_mce_popup.js +inc/tiny_mce/3.5.12/utils/editable_selects.js +inc/tiny_mce/3.5.12/utils/form_utils.js +inc/tiny_mce/3.5.12/utils/mctabs.js +inc/tiny_mce/3.5.12/utils/validate.js inc/treemenu/TreeMenu.php inc/treemenu/index.htm inc/zip/Zip.php diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 05e2a432..8a47c6e9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,32 +1,90 @@ -image: tetraweb/php - stages: + - validate - test - - deploy + - package before_script: - - apt-get update - - apt-get install zip unzip - - cd api - - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - - php composer-setup.php - - php -r "unlink('composer-setup.php');" - - php composer.phar update - -test: + - bash ci/docker_install.sh > /dev/null + +validate:7.2: + image: php:7.2 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:7.1: + image: php:7.1 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:7.0: + image: php:7.0 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:5.6: + image: php:5.6 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:5.5: + image: php:5.5 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:5.4: + image: php:5.4 + stage: validate + script: + - bash ci/php_lint.sh ./ + +validate:5.3: + image: php:5.3 + stage: validate + script: + - bash ci/php_lint.sh ./ + +test:7.1: + image: php:7.1 + stage: test + script: + - cd api + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" + - php composer.phar update + - php composer.phar install + - cd Tests + - phpunit + +test:7.2: + image: php:7.2 stage: test script: - - composer install + - cd api + - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + - php composer-setup.php + - php -r "unlink('composer-setup.php');" + - php composer.phar update + - php composer.phar install - cd Tests - phpunit -deploy: +package: + image: tetraweb/php when: manual - stage: deploy + stage: package script: + - apt-get update + - apt-get install zip unzip + - cd api - composer install --no-dev - cd ../ci - bash build_zip.sh artifacts: paths: - - release.zip \ No newline at end of file + - release.zip diff --git a/admin/admin_main.php b/admin/admin_main.php index 0d6dcefc..59898d18 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -54,7 +54,15 @@ else { ?>
- +

diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php index 96ab9f9f..75d15d92 100644 --- a/admin/admin_reply_ticket.php +++ b/admin/admin_reply_ticket.php @@ -189,15 +189,20 @@ if ($hesk_settings['attachments']['use'] && !empty($attachments)) { // Add reply $html = $modsForHesk_settings['rich_text_for_tickets']; if ($submit_as_customer) { - hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "

{$hesklang['creb']} {$_SESSION['name']}") . "',NOW(),'" . hesk_dbEscape($myattachments) . "', '" . $html . "')"); + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "

{$hesklang['creb']} {$_SESSION['name']}") . "', NOW(),'" . hesk_dbEscape($myattachments) . "', '" . $html . "')"); } else { - hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "',NOW(),'" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')"); + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "', NOW(),'" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')"); } /* Track ticket status changes for history */ $revision = ''; /* Change the status of priority? */ +$audit_priority = null; +$audit_closed = null; +$audit_status = null; +$audit_customer_status = null; +$audit_assigned_self = null; if (!empty($_POST['set_priority'])) { $priority = intval(hesk_POST('priority')); if ($priority < 0 || $priority > 3) { @@ -211,9 +216,17 @@ if (!empty($_POST['set_priority'])) { 3 => $hesklang['low'] ); - $revision = sprintf($hesklang['thist8'], hesk_date(), $options[$priority], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $plain_options = array( + 0 => 'critical', + 1 => 'high', + 2 => 'medium', + 3 => 'low' + ); + + $priority_sql = ",`priority`='$priority' "; - $priority_sql = ",`priority`='$priority', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_priority = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => $plain_options[$priority]); } else { $priority_sql = ""; } @@ -238,8 +251,11 @@ if ($ticket['locked']) { $newStatus = hesk_dbFetchAssoc($newStatusRs); if ($newStatus['IsClosed'] && hesk_checkPermission('can_resolve', 0)) { - $revision = sprintf($hesklang['thist3'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . ", `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_closed = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status) + ); + $sql_status = " , `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . " "; // Lock the ticket if customers are not allowed to reopen tickets if ($hesk_settings['custopen'] != 1) { @@ -247,8 +263,8 @@ if ($ticket['locked']) { } } else { // Ticket isn't being closed, just add the history to the sql query (or tried to close but doesn't have permission) - $revision = sprintf($hesklang['thist9'], hesk_date(), $hesklang[$newStatus['Key']], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status)); } } } // -> Submit as Customer reply @@ -259,8 +275,8 @@ elseif ($submit_as_customer) { $new_status = $customerReplyStatus['ID']; if ($ticket['status'] != $new_status) { - $revision = sprintf($hesklang['thist9'], hesk_date(), $hesklang['wait_reply'], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_customer_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status)); } } // -> Default: submit as "Replied by staff" else { @@ -278,12 +294,21 @@ $sql .= $submit_as_customer ? "`lastreplier`='0', `replierid`='0' " : "`lastrepl if ($time_worked == '00:00:00') { $sql .= ", `lastchange` = NOW() "; } else { + $parts = explode(':', $ticket['time_worked']); + $seconds = ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2]; + + $parts = explode(':', $time_worked); + $seconds += ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2]; + + require(HESK_PATH . 'inc/reporting_functions.inc.php'); + $ticket['time_worked'] = hesk_SecondsToHHMMSS($seconds); + $sql .= ",`time_worked` = ADDTIME(`time_worked`,'" . hesk_dbEscape($time_worked) . "') "; } if (!empty($_POST['assign_self']) && (hesk_checkPermission('can_assign_self', 0) || (isset($_REQUEST['isManager']) && $_REQUEST['isManager']))) { - $revision = sprintf($hesklang['thist2'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql .= " , `owner`=" . intval($_SESSION['id']) . ", `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_assigned_self = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $sql .= " , `owner`=" . intval($_SESSION['id']) . " "; } $sql .= " $priority_sql "; @@ -306,6 +331,29 @@ unset($sql); /* Update number of replies in the users table */ hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `replies`=`replies`+1 WHERE `id`='" . intval($_SESSION['id']) . "'"); +//-- Insert necessary audit trail records +if ($audit_priority != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_priority', hesk_date(), $audit_priority); +} + +if ($audit_closed != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_closed', hesk_date(), $audit_closed); +} + +if ($audit_status != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(), $audit_status); +} + +if ($audit_customer_status != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(), + $audit_customer_status); +} + +if ($audit_assigned_self != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_assigned_self', hesk_date(), $audit_assigned_self); +} + + // --> Prepare reply message // 1. Generate the array with ticket info that can be used in emails @@ -324,7 +372,9 @@ $info = array( 'dt' => hesk_date($ticket['dt'], true), 'lastchange' => hesk_date($ticket['lastchange'], true), 'id' => $ticket['id'], - 'language' => $ticket['language'] + 'language' => $ticket['language'], + 'time_worked' => $ticket['time_worked'], + 'last_reply_by' => ($submit_as_customer ? $ticket['name'] : $_SESSION['name']), ); // 2. Add custom fields to the array diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 1e96c3d6..004cfc2e 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -93,19 +93,20 @@ if ($hesk_settings['attachments']['use'] && !defined('HESK_DEMO')) { $tmp = @ini_get('upload_max_filesize'); if ($tmp) { $last = strtoupper(substr($tmp, -1)); + $number = substr($tmp, 0, -1); switch ($last) { case 'K': - $tmp = $tmp * 1024; + $tmp = $number * 1024; break; case 'M': - $tmp = $tmp * 1048576; + $tmp = $number * 1048576; break; case 'G': - $tmp = $tmp * 1073741824; + $tmp = $number * 1073741824; break; default: - $tmp = $tmp; + $tmp = $number; } if ($tmp < $hesk_settings['attachments']['max_size']) { @@ -117,19 +118,20 @@ if ($hesk_settings['attachments']['use'] && !defined('HESK_DEMO')) { $tmp = @ini_get('post_max_size'); if ($tmp) { $last = strtoupper(substr($tmp, -1)); + $number = substr($tmp, 0, -1); switch ($last) { case 'K': - $tmp = $tmp * 1024; + $tmp = $number * 1024; break; case 'M': - $tmp = $tmp * 1048576; + $tmp = $number * 1048576; break; case 'G': - $tmp = $tmp * 1073741824; + $tmp = $number * 1073741824; break; default: - $tmp = $tmp; + $tmp = $number; } if ($tmp < ($hesk_settings['attachments']['max_size'] * $hesk_settings['attachments']['max_number'] + 524288)) { @@ -355,86 +357,121 @@ $modsForHesk_settings = mfh_getSettings(); : - - + - ' . $hesklang['hud'] . ' '; - } elseif ($latest != -1) { - // Is this a beta/dev version? - if (strpos($hesk_settings['hesk_version'], 'beta') || strpos($hesk_settings['hesk_version'], 'dev') || strpos($hesk_settings['hesk_version'], 'RC')) { - echo ' ' . $hesklang['beta'] . ' '; ?> ' . $hesklang['hnw'] . ' '; ?> - - + - + + + + + + + + + - + target="_blank"> + : - - + - ' . $hesklang['beta'] . ' '; ?> ' . $hesklang['mfh_up_to_date'] . ''; - } else { - ?> - - - + - + + + + + + + + - - + + @@ -2195,6 +2232,106 @@ $modsForHesk_settings = mfh_getSettings();

+
+ +
+

+

'; ?> +
+
+

+ + +

+ +
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
+
+ +
+ + + +
+
@@ -3247,6 +3384,27 @@ $modsForHesk_settings = mfh_getSettings(); +
+ +
+
+ +
+
+