Merge remote-tracking branch 'origin/master' into 457-category-descriptions

master
Mike Koch 7 years ago
commit 05f79ecfa9

@ -355,86 +355,121 @@ $modsForHesk_settings = mfh_getSettings();
<td class="text-right">
<?php echo $hesklang['v']; ?>:
</td>
<?php
$cellClass = '';
if ($hesk_settings['check_updates']) {
$latest = hesk_checkVersion();
if ($latest === true) {
$cellClass = 'success';
} elseif ($latest != -1) {
$cellClass = 'warning';
}
}
?>
<td class="pad-right-10 <?php echo $cellClass; ?>">
<td class="pad-right-10" id="hesk-version-status">
<?php echo $hesk_settings['hesk_version']; ?>
<?php
if ($hesk_settings['check_updates']) {
if ($latest === true) {
echo ' - <span class="green">' . $hesklang['hud'] . '</span> ';
} 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 ' <span class="dark-orange">' . $hesklang['beta'] . '</span> '; ?> <a
href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
} else {
echo ' - <span class="dark-orange bold">' . $hesklang['hnw'] . '</span> '; ?> <a
href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank"><?php echo $hesklang['getup']; ?></a><?php
}
} else {
?> - <a
href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
}
} else {
?> - <a
<?php if ($hesk_settings['check_updates']) : ?>
-
<i class="spinner fa fa-spin fa-spinner"></i>
<span class="up-to-date green" style="display: none">
<?php echo $hesklang['hud']; ?>
</span>
<span class="beta-version orange" style="display: none">
<?php echo $hesklang['beta']; ?>
<a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a>
</span>
<span class="update-available orange" style="display: none">
<?php echo $hesklang['hnw']; ?>
<a href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank">
<?php echo $hesklang['getup']; ?>
</a>
</span>
<a class="response-error" href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank" style="display: none"><?php echo $hesklang['check4updates']; ?></a>
<script>
var heskUrl = $('p#hesk-path').text();
var $versionStatus = $('#hesk-version-status');
$.ajax({
url: heskUrl + 'api/index.php/v1-public/hesk-version',
method: 'GET',
success: function(data) {
if ('<?php echo $hesk_settings['hesk_version']; ?>' === data.version) {
$versionStatus.addClass('success');
$versionStatus.find('.up-to-date').show();
} else if (<?php echo strpos($hesk_settings['hesk_version'], 'beta') ||
strpos($hesk_settings['hesk_version'], 'dev') ||
strpos($hesk_settings['hesk_version'], 'RC') ? 'true' : 'false'; ?>) {
$versionStatus.addClass('warning');
$versionStatus.find('.beta-version').show();
} else {
$versionStatus.addClass('warning');
$versionStatus.find('.update-available').show();
}
},
error: function() {
$versionStatus.find('.response-error').show();
},
complete: function(data) {
$versionStatus.find('.spinner').hide();
}
});
</script>
<?php else: ?>
- <a
href="https://www.hesk.com/update.php?v=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
}
?>
target="_blank"><?php echo $hesklang['check4updates']; ?></a>
<?php endif; ?>
</td>
</tr>
<tr>
<td class="text-right pad-up-5">
<?php echo $hesklang['mods_for_hesk_version']; ?>:
</td>
<?php
$cellClass = '';
if ($hesk_settings['check_updates']) {
$latest = hesk_checkMfhVersion($modsForHeskVersion);
if ($latest === true) {
$cellClass = 'success';
} elseif ($latest != -1) {
$cellClass = 'warning';
}
}
?>
<td class="pad-right-10 pad-up-5 <?php echo $cellClass; ?>">
<td class="pad-right-10 pad-up-5" id="mfh-version-status">
<?php echo $modsForHeskVersion; ?>
<?php
if ($hesk_settings['check_updates']) {
if (strpos($modsForHeskVersion, 'beta') || strpos($modsForHeskVersion, 'dev') || strpos($modsForHeskVersion, 'RC')) {
echo ' <span class="dark-orange">' . $hesklang['beta'] . '</span> '; ?> <a
href="https://mods-for-hesk.mkochcs.com/versioncheck.php?v=<?php echo $modsForHeskVersion; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a><?php
} elseif ($latest === true) {
echo ' - <span class="green">' . $hesklang['mfh_up_to_date'] . '</span>';
} else {
?> - <a href="https://mods-for-hesk.mkochcs.com" target="_blank"
class="orange bold"><?php echo $hesklang['hnw']; ?></a>
<?php
}
} else {
?> - <a
href="https://mods-for-hesk.mkochcs.com/versioncheck.php?version=<?php echo $modsForHeskVersion; ?>"
<?php if ($hesk_settings['check_updates']) : ?>
-
<i class="spinner fa fa-spin fa-spinner"></i>
<span class="up-to-date green" style="display: none">
<?php echo $hesklang['mfh_up_to_date']; ?>
</span>
<span class="beta-version orange" style="display: none">
<?php echo $hesklang['beta']; ?>
<a href="https://www.mods-for-hesk.com/versioncheck.php?v=<?php echo $modsForHeskVersion; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a>
</span>
<span class="update-available" style="display: none">
<a class="orange" href="https://www.mods-for-hesk.com/versioncheck.php?version=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank">
<?php echo $hesklang['hnw']; ?>
</a>
</span>
<a class="response-error" href="https://www.hesk.com/update.php?version=<?php echo $hesk_settings['hesk_version']; ?>"
target="_blank" style="display: none"><?php echo $hesklang['check4updates']; ?></a>
<?php else: ?>
- <a
href="https://www.mods-for-hesk.com/versioncheck.php?version=<?php echo $modsForHeskVersion; ?>"
target="_blank"><?php echo $hesklang['check4updates']; ?></a>
<?php
}
?>
<?php endif; ?>
<script>
var heskUrl = $('p#hesk-path').text();
var $mfhVersionStatus = $('#mfh-version-status');
$.ajax({
url: heskUrl + 'api/index.php/v1-public/mods-for-hesk-version',
method: 'GET',
success: function(data) {
if ('<?php echo $modsForHeskVersion; ?>' === data.version) {
$mfhVersionStatus.addClass('success');
$mfhVersionStatus.find('.up-to-date').show();
} else if (<?php echo strpos($modsForHeskVersion, 'beta') ||
strpos($modsForHeskVersion, 'dev') ||
strpos($modsForHeskVersion, 'RC') ? 'true' : 'false'; ?>) {
$mfhVersionStatus.addClass('warning');
$mfhVersionStatus.find('.beta-version').show();
} else {
$mfhVersionStatus.addClass('warning');
$mfhVersionStatus.find('.update-available').show();
}
},
error: function() {
$mfhVersionStatus.find('.response-error').show();
},
complete: function(data) {
$mfhVersionStatus.find('.spinner').hide();
}
});
</script>
</td>
</tr>
<tr>
@ -3935,130 +3970,6 @@ $modsForHesk_settings = mfh_getSettings();
}
function hesk_checkVersion()
{
global $hesk_settings;
if ($latest = hesk_getLatestVersion()) {
if (strlen($latest) > 12) {
return -1;
} elseif ($latest == $hesk_settings['hesk_version']) {
return true;
} else {
return $latest;
}
} else {
return -1;
}
} // END hesk_checkVersion()
function hesk_getLatestVersion()
{
global $hesk_settings;
// Do we have a cached version file?
if (file_exists(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt')) {
if (preg_match('/^(\d+)\|([\d.]+)+$/', @file_get_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt'), $matches) && (time() - intval($matches[1])) < 3600) {
return $matches[2];
}
}
// No cached file or older than 3600 seconds, try to get an update
$hesk_version_url = 'https://hesk.com/version';
// Try using cURL
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $hesk_version_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
$latest = curl_exec($ch);
curl_close($ch);
return hesk_cacheLatestVersion($latest);
}
// Try using a simple PHP function instead
if ($latest = @file_get_contents($hesk_version_url)) {
return hesk_cacheLatestVersion($latest);
}
// Can't check automatically, will need a manual check
return false;
} // END hesk_getLatestVersion()
function hesk_cacheLatestVersion($latest)
{
global $hesk_settings;
@file_put_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest.txt', time() . '|' . $latest);
return $latest;
} // END hesk_cacheLatestVersion()
function hesk_checkMfhVersion($currentVersion)
{
if ($latest = hesk_getMfhLatestVersion()) {
if (strlen($latest) > 12) {
return -1;
} elseif ($latest == $currentVersion) {
return true;
} else {
return $latest;
}
} else {
return -1;
}
}
function hesk_getMfhLatestVersion()
{
global $hesk_settings;
// Do we have a cached version file?
if (file_exists(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt')) {
if (preg_match('/^(\d+)\|([\d.]+)+$/', @file_get_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt'), $matches) && (time() - intval($matches[1])) < 3600) {
return $matches[2];
}
}
// No cached file or older than 3600 seconds, try to get an update
$hesk_version_url = 'http://mods-for-hesk.mkochcs.com/latestversion.php';
// Try using cURL
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $hesk_version_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
$latest = curl_exec($ch);
curl_close($ch);
return hesk_cacheMfhLatestVersion($latest);
}
// Try using a simple PHP function instead
if ($latest = file_get_contents($hesk_version_url)) {
return hesk_cacheMfhLatestVersion($latest);
}
// Can't check automatically, will need a manual check
return false;
}
function hesk_cacheMfhLatestVersion($latest)
{
global $hesk_settings;
@file_put_contents(HESK_PATH . $hesk_settings['cache_dir'] . '/__latest-mfh.txt', time() . '|' . $latest);
return $latest;
}
function hesk_testLanguage($return_options = 0)
{
global $hesk_settings, $hesklang, $modsForHesk_settings;

@ -15,6 +15,10 @@ class BasicEmailSender implements EmailSender {
if ($heskSettings['smtp']) {
$mailer->isSMTP();
$mailer->SMTPAuth = true;
//-- We'll set this explicitly below if the user has it enabled.
$mailer->SMTPAutoTLS = false;
if ($heskSettings['smtp_ssl']) {
$mailer->SMTPSecure = "ssl";
} elseif ($heskSettings['smtp_tls']) {

@ -190,7 +190,9 @@ class EmailTemplateParser {
$defaultStatus = $this->statusGateway->getStatusForDefaultAction(DefaultStatusForAction::NEW_TICKET, $heskSettings);
$statusName = hesk_msgToPlain($defaultStatus->localizedNames[$language]);
$category = hesk_msgToPlain($this->categoryGateway->getAllCategories($heskSettings)[$ticket->categoryId]->name);
$owner = hesk_msgToPlain($this->userGateway->getUserById($ticket->ownerId, $heskSettings)->name);
$owner = $this->userGateway->getUserById($ticket->ownerId, $heskSettings);
$ownerName = $owner === null ? $hesklang['unas'] : hesk_msgToPlain($owner->name);
switch ($ticket->priorityId) {
case Priority::CRITICAL:
@ -219,7 +221,7 @@ class EmailTemplateParser {
$msg = str_replace('%%SITE_URL%%', $heskSettings['site_url'], $msg);
$msg = str_replace('%%CATEGORY%%', $category, $msg);
$msg = str_replace('%%PRIORITY%%', $priority, $msg);
$msg = str_replace('%%OWNER%%', $owner, $msg);
$msg = str_replace('%%OWNER%%', $ownerName, $msg);
$msg = str_replace('%%STATUS%%', $statusName, $msg);
$msg = str_replace('%%EMAIL%%', implode(';',$ticket->email), $msg);
$msg = str_replace('%%CREATED%%', $ticket->dateCreated, $msg);

@ -0,0 +1,56 @@
<?php
namespace Controllers\System;
class HeskVersionController {
static function getHeskVersion() {
global $hesk_settings;
return self::getLatestVersion('__latest.txt', 'https://www.hesk.com/version', $hesk_settings);
}
static function getModsForHeskVersion() {
global $hesk_settings;
return self::getLatestVersion('__latest-mfh.txt', 'https://www.mods-for-hesk.com/latestversion.php', $hesk_settings);
}
private static function getLatestVersion($fileName, $url, $hesk_settings) {
if (file_exists(__DIR__ . '/../../../' . $hesk_settings['cache_dir'] . '/' . $fileName) &&
preg_match('/^(\d+)\|([\d.]+)+$/',
@file_get_contents(__DIR__ . '/../../../' . $hesk_settings['cache_dir'] . '/' . $fileName), $matches) &&
(time() - intval($matches[1])) < 3600) {
return output(array('version' => $matches[2]));
}
// Try using cURL
if (function_exists('curl_init')) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 6);
$latest = curl_exec($ch);
curl_close($ch);
self::cacheLatestVersion($latest, $fileName, $hesk_settings);
return output(array('version' => $latest));
}
// Try using a simple PHP function instead
if ($latest = @file_get_contents($url)) {
self::cacheLatestVersion($latest, $fileName, $hesk_settings);
return output(array('version' => $latest));
}
// Can't check automatically, will need a manual check
return http_response_code(408);
}
private static function cacheLatestVersion($latest, $fileName, $hesk_settings) {
@file_put_contents(__DIR__ . '/../../../' . $hesk_settings['cache_dir'] . '/' . $fileName,
time() . '|' . $latest);
}
}

@ -15,26 +15,37 @@ function handle404() {
), 404);
}
function before() {
function globalBefore() {
if (defined('HESK_DEMO') && $_SERVER['REQUEST_METHOD'] !== 'GET') {
print_error('Demo Mode', 'Only read-only commands are available in demo mode!', null, 401);
die();
}
}
function internalHandler() {
buildUserContextFromSession();
}
function authTokenHandler() {
assertApiIsEnabled();
$token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN');
buildUserContext($token);
}
function internalOrAuthHandler() {
$internalUse = \BusinessLogic\Helpers::getHeader('X-INTERNAL-CALL');
if ($internalUse === 'true') {
buildUserContextFromSession();
} elseif (preg_match('/\/v1\/tickets\/.+\/attachments\/\d+/', $_SERVER['PATH_INFO'])) {
//-- TODO Clean this up
return;
internalHandler();
} else {
assertApiIsEnabled();
$token = \BusinessLogic\Helpers::getHeader('X-AUTH-TOKEN');
buildUserContext($token);
authTokenHandler();
}
}
function publicHandler() {
//-- No-op
}
function assertApiIsEnabled() {
global $applicationContext, $hesk_settings;
@ -172,34 +183,55 @@ function fatalErrorShutdownHandler() {
}
}
Link::before('before');
Link::before('globalBefore');
Link::all(array(
// Categories
'/v1/categories' => [\Controllers\Categories\CategoryController::class . '::printAllCategories'],
'/v1/categories/{i}' => \Controllers\Categories\CategoryController::class,
'/v1/categories' => action(\Controllers\Categories\CategoryController::class . '::printAllCategories'),
'/v1/categories/{i}' => action(\Controllers\Categories\CategoryController::class),
// Tickets
'/v1/tickets' => \Controllers\Tickets\CustomerTicketController::class,
'/v1/tickets' => action(\Controllers\Tickets\CustomerTicketController::class),
// Tickets - Staff
'/v1/staff/tickets/{i}' => \Controllers\Tickets\StaffTicketController::class,
'/v1/staff/tickets/{i}' => action(\Controllers\Tickets\StaffTicketController::class),
// Attachments
'/v1/tickets/{a}/attachments/{i}' => \Controllers\Attachments\PublicAttachmentController::class . '::getRaw',
'/v1/staff/tickets/{i}/attachments' => \Controllers\Attachments\StaffTicketAttachmentsController::class,
'/v1/staff/tickets/{i}/attachments/{i}' => \Controllers\Attachments\StaffTicketAttachmentsController::class,
'/v1/tickets/{a}/attachments/{i}' => action(\Controllers\Attachments\PublicAttachmentController::class . '::getRaw'),
'/v1/staff/tickets/{i}/attachments' => action(\Controllers\Attachments\StaffTicketAttachmentsController::class),
'/v1/staff/tickets/{i}/attachments/{i}' => action(\Controllers\Attachments\StaffTicketAttachmentsController::class),
// Statuses
'/v1/statuses' => \Controllers\Statuses\StatusController::class,
'/v1/statuses' => action(\Controllers\Statuses\StatusController::class),
// Settings
'/v1/settings' => \Controllers\Settings\SettingsController::class,
'/v1/settings' => action(\Controllers\Settings\SettingsController::class),
/* Internal use only routes */
// Resend email response
'/v1-internal/staff/tickets/{i}/resend-email' => \Controllers\Tickets\ResendTicketEmailToCustomerController::class,
'/v1-internal/staff/tickets/{i}/resend-email' =>
action(\Controllers\Tickets\ResendTicketEmailToCustomerController::class, SecurityHandler::INTERNAL),
// Custom Navigation
'/v1-internal/custom-navigation/all' => \Controllers\Navigation\CustomNavElementController::class . '::getAll',
'/v1-internal/custom-navigation' => \Controllers\Navigation\CustomNavElementController::class,
'/v1-internal/custom-navigation/{i}' => \Controllers\Navigation\CustomNavElementController::class,
'/v1-internal/custom-navigation/{i}/sort/{s}' => \Controllers\Navigation\CustomNavElementController::class . '::sort',
'/v1-internal/custom-navigation/all' =>
action(\Controllers\Navigation\CustomNavElementController::class . '::getAll', SecurityHandler::INTERNAL),
'/v1-internal/custom-navigation' =>
action(\Controllers\Navigation\CustomNavElementController::class, SecurityHandler::INTERNAL),
'/v1-internal/custom-navigation/{i}' =>
action(\Controllers\Navigation\CustomNavElementController::class, SecurityHandler::INTERNAL),
'/v1-internal/custom-navigation/{i}/sort/{s}' =>
action(\Controllers\Navigation\CustomNavElementController::class . '::sort', SecurityHandler::INTERNAL),
'/v1-public/hesk-version' =>
action(\Controllers\System\HeskVersionController::class . '::getHeskVersion', SecurityHandler::OPEN),
'/v1-public/mods-for-hesk-version' =>
action(\Controllers\System\HeskVersionController::class . '::getModsForHeskVersion', SecurityHandler::OPEN),
// Any URL that doesn't match goes to the 404 handler
'404' => 'handle404'
));
));
function action($class, $securityHandler = SecurityHandler::AUTH_TOKEN) {
return [$class, $class, $securityHandler];
}
class SecurityHandler {
const OPEN = 'publicHandler';
const INTERNAL = 'internalHandler';
const AUTH_TOKEN = 'authTokenHandler';
const INTERNAL_OR_AUTH_TOKEN = 'internalOrAuthHandler';
}

@ -1,4 +1,4 @@
<?php
// Define the current build
define('MODS_FOR_HESK_BUILD', 42);
define('MODS_FOR_HESK_BUILD', 43);

@ -43,6 +43,7 @@ if (is_dir(HESK_PATH . 'install')) {
$modsForHesk_settings = mfh_getSettings();
}
header('X-UA-Compatible: IE=edge');
?>
<!DOCTYPE html>
<html>
@ -55,10 +56,10 @@ if (is_dir(HESK_PATH . 'install')) {
<link href="<?php echo HESK_PATH; ?>css/datepicker.css" type="text/css" rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/bootstrap.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"
rel="stylesheet"/>
<?php if ($modsForHesk_settings['use_bootstrap_theme'] != 0) { ?>
<link href="<?php echo HESK_PATH; ?>css/bootstrap-theme.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"
rel="stylesheet" <?php if ($modsForHesk_settings['use_bootstrap_theme'] == 0) {
echo 'disabled';
} ?>>
rel="stylesheet" />
<?php } ?>
<link href="<?php echo HESK_PATH; ?>css/mods-for-hesk.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"
rel="stylesheet"/>
<link href="<?php echo HESK_PATH; ?>css/hesk_newStyle.css?v=<?php echo MODS_FOR_HESK_BUILD; ?>" type="text/css"

@ -21,6 +21,8 @@ if (!defined('IN_SCRIPT')) {
define('ADMIN_PAGE', true);
$modsForHesk_settings = mfh_getSettings();
header('X-UA-Compatible: IE=edge');
?>
<!DOCTYPE html>
<html>

@ -16,7 +16,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');}
// We will be installing this HESK version:
define('HESK_NEW_VERSION','2.7.3');
define('MODS_FOR_HESK_NEW_VERSION','3.1.0');
define('MODS_FOR_HESK_NEW_VERSION','3.1.1');
define('REQUIRE_PHP_VERSION','5.3.0');
define('REQUIRE_MYSQL_VERSION','5.0.7');

@ -90,6 +90,8 @@ if ($version == 2) {
execute307Scripts();
} elseif ($version == 42) {
execute310Scripts();
} elseif ($version == 43) {
execute311Scripts();
} else {
$response = 'The version "' . $version . '" was not recognized. Check the value submitted and try again.';
print $response;

@ -51,6 +51,7 @@ $buildToVersionMap = array(
40 => '3.0.6',
41 => '3.0.7',
42 => '3.1.0',
43 => '3.1.1',
);
function echoInitialVersionRows($version, $build_to_version_map)

@ -122,6 +122,9 @@ function processUpdates(startingVersion) {
} else if (startingVersion < 42) {
startVersionUpgrade('310');
executeUpdate(42, '310', '3.1.0');
} else if (startingVersion < 43) {
startVersionUpgrade('311');
executeUpdate(43, '311', '3.1.1');
} else {
installationFinished();
}

@ -118,6 +118,7 @@ hesk_dbConnect();
<select name="current-version" class="form-control">
<option disabled>Select One, or "No Previous Installation" Below</option>
<optgroup label="Mods for HESK 3">
<option value="42">3.1.0</option>
<option value="41">3.0.7</option>
<option value="40">3.0.6</option>
<option value="39">3.0.5</option>

@ -1123,4 +1123,11 @@ function execute310Scripts() {
executeQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "settings` WHERE `Key` IN ('rtl', 'admin_color_scheme')");
updateVersion('3.1.0');
}
function execute311Scripts() {
global $hesk_settings;
hesk_dbConnect();
updateVersion('3.1.1');
}
Loading…
Cancel
Save