diff --git a/admin/admin_settings.php b/admin/admin_settings.php
index 1a171091..be6c3bae 100644
--- a/admin/admin_settings.php
+++ b/admin/admin_settings.php
@@ -2186,6 +2186,7 @@ if ( defined('HESK_DEMO') )
|
|
|
+ |
|
|
@@ -2198,17 +2199,31 @@ if ( defined('HESK_DEMO') )
$checkedEcho = ($row['IsClosed'] == 1) ? 'checked="checked"' : '';
$isDisabled = false;
if ($row['IsNewTicketStatus'] || $row['IsClosedByClient'] || $row['IsCustomerReplyStatus'] ||
- $row['IsStaffClosedOption'] || $row['IsStaffReopenedStatus'] || $row['IsDefaultStaffReplyStatus']
- || $row['LockedTicketStatus'])
+ $row['IsStaffClosedOption'] || $row['IsStaffReopenedStatus'] || $row['IsDefaultStaffReplyStatus'] ||
+ $row['LockedTicketStatus'] || $row['IsAutocloseOption'])
{
$isDisabled = true;
}
+ $yesSelected = $customersOnlySelected = $staffOnlySelected = $noSelected = '';
+ if ($row['Closable'] == 'yes') { $yesSelected = 'selected'; }
+ elseif ($row['Closable'] == 'conly') { $customersOnlySelected = 'selected'; }
+ elseif ($row['Closable'] == 'sonly') { $staffOnlySelected = 'selected'; }
+ else { $noSelected = 'selected'; }
+
echo '';
echo ''.$hesklang[$row['ShortNameContentKey']].' | '; //Name
echo ' | '; // Short Name Language File
echo ' | '; // Long Name Language File
echo ' | '; // Text Color
+ echo '
+
+ | ';
echo ' | '; // Resolved Status?
echo '';
if ($isDisabled)
@@ -2228,6 +2243,14 @@ if ( defined('HESK_DEMO') )
echo ' | | '; // Short Name Language File
echo ' | '; // Long Name Language File
echo ' | '; // Text Color
+ echo '
+
+ | ';
echo ' | '; // Resolved Status?
echo ' | '; //Empty placeholder where the delete row is.
echo '
';
@@ -2342,6 +2365,21 @@ if ( defined('HESK_DEMO') )
+
diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php
index 96615491..00acc2b4 100644
--- a/admin/admin_settings_save.php
+++ b/admin/admin_settings_save.php
@@ -529,10 +529,10 @@ while ($row = $results->fetch_assoc())
} else
{
//-- Update the information in the database with what is on the page
- $query = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `ShortNameContentKey` = ?, `TicketViewContentKey` = ?, `TextColor` = ?, `IsClosed` = ? WHERE `ID` = ?";
+ $query = "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `ShortNameContentKey` = ?, `TicketViewContentKey` = ?, `TextColor` = ?, `IsClosed` = ?, `Closable` = ? WHERE `ID` = ?";
$stmt = hesk_dbConnect()->prepare($query);
$isStatusClosed = (isset($_POST['s'.$row['ID'].'_isClosed']) ? 1 : 0);
- $stmt->bind_param('sssii', $_POST['s'.$row['ID'].'_shortName'], $_POST['s'.$row['ID'].'_longName'], $_POST['s'.$row['ID'].'_textColor'], $isStatusClosed, $row['ID']);
+ $stmt->bind_param('sssisi', $_POST['s'.$row['ID'].'_shortName'], $_POST['s'.$row['ID'].'_longName'], $_POST['s'.$row['ID'].'_textColor'], $isStatusClosed, $_POST['s'.$row['ID'].'_closable'], $row['ID']);
$stmt->execute();
}
}
@@ -555,7 +555,7 @@ if ($_POST['sN_shortName'] != null && $_POST['sN_longName'] != null && $_POST['s
$insert = "INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (`ID`, `ShortNameContentKey`, `TicketViewContentKey`, `TextColor`, `IsClosed`) VALUES (?, ?, ?, ?, ?)";
$stmt = hesk_dbConnect()->prepare($insert);
$isClosed = isset($_POST['sN_isClosed']) ? 1 : 0;
- $stmt->bind_param('isssi', $nextValue, $_POST['sN_shortName'], $_POST['sN_longName'], $_POST['sN_textColor'], $isClosed);
+ $stmt->bind_param('isssis', $nextValue, $_POST['sN_shortName'], $_POST['sN_longName'], $_POST['sN_textColor'], $isClosed, $_POST['sN_closable']);
$stmt->execute();
}
@@ -605,6 +605,12 @@ $stmt = hesk_dbConnect()->prepare($updateQuery);
$stmt->bind_param('i', $_POST['lockedTicketStatus']);
$stmt->execute();
+hesk_dbConnect()->query($defaultQuery . "`IsAutocloseOption` = 0");
+$updateQuery = $defaultQuery . "`IsAutocloseOption` = 1 WHERE `ID` = ?";
+$stmt = hesk_dbConnect()->prepare($updateQuery);
+$stmt->bind_param('i', $_POST['autocloseTicketOption']);
+$stmt->execute();
+
$set['hesk_version'] = $hesk_settings['hesk_version'];
// Save the modsForHesk_settings.inc.php file
diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php
index 6f587417..9e440aae 100644
--- a/admin/admin_ticket.php
+++ b/admin/admin_ticket.php
@@ -672,7 +672,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
'.$hesklang['asss'].']' : $hesklang['unas']);
+ ($can_assign_self ? $hesklang['unas'].' —
'.$hesklang['asss'].'' : $hesklang['unas']);
?>
@@ -847,18 +847,19 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
}
}
- $isTicketClosedSql = 'SELECT `IsClosed` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `ID` = '.$ticket['status'];
+ $isTicketClosedSql = 'SELECT `IsClosed`, `Closable` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `ID` = '.$ticket['status'];
$isTicketClosedRow = hesk_dbQuery($isTicketClosedSql)->fetch_assoc();
$isTicketClosed = $isTicketClosedRow['IsClosed'];
+ $isClosable = $isTicketClosedRow['Closable'] == 'yes' || $isTicketClosedRow['Closable'] == 'sonly';
echo '';
- if ($isTicketClosed == 0) // Ticket is still open
+ if ($isTicketClosed == 0 && $isClosable) // Ticket is still open
{
echo '
'.$hesklang['close_action'].'';
}
- else
+ elseif ($isTicketClosed == 1)
{
echo '
diff --git a/admin/index.php b/admin/index.php
index 0165d3ee..2ddf4be4 100644
--- a/admin/index.php
+++ b/admin/index.php
@@ -260,35 +260,37 @@ function do_login()
$revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['auto']);
$dt = date('Y-m-d H:i:s',time() - $hesk_settings['autoclose']*86400);
- // Notify customer of closed ticket?
- if ($hesk_settings['notify_closed'])
- {
- $closedStatusRs = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsDefaultStaffReplyStatus` = 1');
- $closedStatus = hesk_dbFetchAssoc($closedStatusRs);
- // Get list of tickets
- $result = hesk_dbQuery("SELECT * FROM `".$hesk_settings['db_pfix']."tickets` WHERE `status` = ".$closedStatus['ID']." AND `lastchange` <= '".hesk_dbEscape($dt)."' ");
- if (hesk_dbNumRows($result) > 0)
- {
- global $ticket;
- // Load required functions?
- if ( ! function_exists('hesk_notifyCustomer') )
- {
- require(HESK_PATH . 'inc/email_functions.inc.php');
- }
+ $closedStatusRs = hesk_dbQuery('SELECT `ID`, `Closable` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsDefaultStaffReplyStatus` = 1');
+ $closedStatus = hesk_dbFetchAssoc($closedStatusRs);
+ // Are we allowed to close tickets in this status?
+ if ($closedStatus['Closable'] == 'yes' || $closedStatus['Closable'] == 'sonly') {
+ // Notify customer of closed ticket?
+ if ($hesk_settings['notify_closed']) {
+ // Get list of tickets
+ $result = hesk_dbQuery("SELECT * FROM `" . $hesk_settings['db_pfix'] . "tickets` WHERE `status` = " . $closedStatus['ID'] . " AND `lastchange` <= '" . hesk_dbEscape($dt) . "' ");
+ if (hesk_dbNumRows($result) > 0) {
+ global $ticket;
- while ($ticket = hesk_dbFetchAssoc($result))
- {
- $ticket['dt'] = hesk_date($ticket['dt'], true);
- $ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
- $ticket = hesk_ticketToPlain($ticket, 1, 0);
- hesk_notifyCustomer('ticket_closed');
+ // Load required functions?
+ if (!function_exists('hesk_notifyCustomer')) {
+ require(HESK_PATH . 'inc/email_functions.inc.php');
+ }
+
+ while ($ticket = hesk_dbFetchAssoc($result)) {
+ $ticket['dt'] = hesk_date($ticket['dt'], true);
+ $ticket['lastchange'] = hesk_date($ticket['lastchange'], true);
+ $ticket = hesk_ticketToPlain($ticket, 1, 0);
+ hesk_notifyCustomer('ticket_closed');
+ }
}
}
- }
- // Update ticket statuses and history in database
- hesk_dbQuery("UPDATE `".$hesk_settings['db_pfix']."tickets` SET `status`='3', `closedat`=NOW(), `closedby`='-1', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `status` = '2' AND `lastchange` <= '".hesk_dbEscape($dt)."' ");
+ // Update ticket statuses and history in database if we're allowed to do so
+ $defaultCloseRs = hesk_dbQuery('SELECT `ID` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `IsAutocloseOption` = 1');
+ $defaultCloseStatus = hesk_dbFetchAssoc($defaultCloseRs);
+ hesk_dbQuery("UPDATE `" . $hesk_settings['db_pfix'] . "tickets` SET `status`=".intval($defaultCloseStatus['ID']).", `closedat`=NOW(), `closedby`='-1', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `status` = '".$closedStatus['ID']."' AND `lastchange` <= '" . hesk_dbEscape($dt) . "' ");
+ }
}
/* Redirect to the destination page */
diff --git a/install/mods-for-hesk/sql/installSql.php b/install/mods-for-hesk/sql/installSql.php
index 84fddf67..4c5b3cad 100644
--- a/install/mods-for-hesk/sql/installSql.php
+++ b/install/mods-for-hesk/sql/installSql.php
@@ -381,7 +381,7 @@ function execute211Scripts() {
}
function execute211FileUpdate() {
- //-- Add the boostrap theme property to modsForHesk_settings.inc.php
+ //-- Add the new kb article visibility property to modsForHesk_settings.inc.php
$file = file_get_contents(HESK_PATH . 'modsForHesk_settings.inc.php');
//-- Only add the additional settings if they aren't already there.
@@ -402,5 +402,13 @@ function execute220Scripts() {
global $hesk_settings;
hesk_dbConnect();
+ executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` ADD COLUMN `IsAutocloseOption` INT NOT NULL DEFAULT 0");
+
+ // There will only ever be one row
+ executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `IsAutocloseOption` = 1 WHERE `IsStaffClosedOption` = 1");
+
+ executeQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` ADD COLUMN `Closable` VARCHAR(10) NOT NULL");
+ executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `Closable` = 'yes'");
executeQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` SET `Value` = '2.2.0' WHERE `Key` = 'modsForHeskVersion'");
-}
\ No newline at end of file
+}
+// END Version 2.2.0
\ No newline at end of file
diff --git a/language/en/text.php b/language/en/text.php
index c08f7f67..ef5aa220 100644
--- a/language/en/text.php
+++ b/language/en/text.php
@@ -47,7 +47,18 @@ $hesklang['email_template_saved'] = 'The email template %s has been saved
$hesklang['error_saving_template'] = 'An error occurred when trying to save the email template!';
$hesklang['can_man_email_tpl'] = 'Edit email templates';
$hesklang['email_template_directory_not_writable'] = 'The email template %s is not writable by HESK. Please CHMOD it to 0666.'; // %s: template file name
-
+$hesklang['closable_question'] = 'Closable?';
+$hesklang['closable_description'] = 'This setting is ignored if the "Closed?" checkbox is checked for this status.
+
Determines if the customer staff is able to close a ticket in this status.
+
Yes: Both customers and staff can close a ticket in this status.
+
Customers only: Customers can close a ticket in this status, but staff cannot.
+
Staff only: Staff can close a ticket in this status, but customers cannot.
+
No: No one is allowed to close a ticket in this status.'; // " = "
+$hesklang['customers_only'] = 'Customers only';
+$hesklang['staff_only'] = 'Staff only';
+$hesklang['yes_title_case'] = 'Yes';
+$hesklang['no_title_case'] = 'No';
+$hesklang['autoclose_ticket_status'] = 'When a ticket is closed automatically, change the status to';
// ADDED OR MODIFIED IN Mods for HESK 2.1.1
$hesklang['new_article_default_type'] = 'Default Type for New Articles';
diff --git a/ticket.php b/ticket.php
index af8a582d..069d8e14 100644
--- a/ticket.php
+++ b/ticket.php
@@ -264,9 +264,17 @@ require_once(HESK_PATH . 'inc/header.inc.php');
: