update v1.2.5

This commit is contained in:
Yuri Karamian
2026-07-15 00:03:43 +02:00
parent fc2d2d4df6
commit 7a19e78d51
4 changed files with 138 additions and 51 deletions
@@ -3,7 +3,7 @@
* WHMCS Server Module - Hetzner VPS
*
* @package WHMCS
* @version 1.2.4
* @version 1.2.5
* @copyright Copyright (c) ArkHost 2025
* @author ArkHost <support@arkhost.com>
* @link https://arkhost.com
@@ -104,6 +104,57 @@ function ArkHostHetznerVPS_GetConfigurableOption(array $params, $optionName) {
return null;
}
/**
* Convert a legacy Hetzner datacenter name (for example fsn1-dc14) to the
* corresponding location name (fsn1). Location names are normalized to
* lowercase, while numeric IDs remain unchanged.
*/
function ArkHostHetznerVPS_NormalizeLocation($location) {
if (!is_scalar($location)) {
return '';
}
$location = trim((string)$location);
if ($location === '') {
return '';
}
if (preg_match('/^([a-z0-9]+)-dc[0-9]+$/i', $location, $matches)) {
return strtolower($matches[1]);
}
return strtolower($location);
}
/**
* Resolve the server location while remaining compatible with configurable
* options named either "Location" or the former "Datacenter".
*/
function ArkHostHetznerVPS_GetLocationOption(array $params, $default = NULL) {
foreach (array('configoptions', 'customfields') as $collection) {
if (!isset($params[$collection]) || !is_array($params[$collection])) {
continue;
}
// Prefer the current option name if both current and legacy options
// happen to exist on the same product.
foreach (array('location', 'datacenter') as $optionName) {
foreach ($params[$collection] as $name => $value) {
$normalizedName = strtolower(trim((string)$name));
if ($normalizedName === $optionName && $value !== '') {
return ArkHostHetznerVPS_NormalizeLocation($value);
}
}
}
}
// Keep using the original module setting key so existing WHMCS products
// retain their configoption3 value after upgrading.
return ArkHostHetznerVPS_NormalizeLocation(
ArkHostHetznerVPS_GetOption($params, 'datacenter', $default)
);
}
function ArkHostHetznerVPS_API(array $params) {
$url = 'https://api.hetzner.cloud/v1/';
$data = [];
@@ -125,8 +176,8 @@ function ArkHostHetznerVPS_API(array $params) {
$method = 'GET';
break;
case 'Datacenters':
$url .= 'datacenters';
case 'Locations':
$url .= 'locations?per_page=50';
$method = 'GET';
break;
@@ -160,10 +211,11 @@ function ArkHostHetznerVPS_API(array $params) {
)
);
// Add datacenter if specified
$datacenter = ArkHostHetznerVPS_GetOption($params, 'datacenter');
if ($datacenter) {
$data['datacenter'] = $datacenter;
// Hetzner removed the datacenter request property on 1 July 2026.
// Normalize legacy values such as fsn1-dc14 before sending location.
$location = ArkHostHetznerVPS_GetLocationOption($params);
if ($location) {
$data['location'] = $location;
}
// Handle backups
@@ -975,9 +1027,11 @@ function ArkHostHetznerVPS_ConfigOptions() {
'Type' => 'dropdown',
'Options' => array(),
),
// Keep the original array key and position for existing WHMCS product
// settings. Only the Hetzner-facing value and admin label have changed.
'datacenter' => array(
'FriendlyName' => 'Datacenter',
'Description' => 'The datacenter location for the server.',
'FriendlyName' => 'Location',
'Description' => 'The Hetzner location for the server (Configurable option: Location or legacy datacenter).',
'Type' => 'dropdown',
'Options' => array(),
),
@@ -993,7 +1047,7 @@ function ArkHostHetznerVPS_ConfigOptions() {
),
'floating_ip_location' => array(
'FriendlyName' => 'Floating IP Location',
'Description' => 'Location for floating IPs (same as datacenter)',
'Description' => 'Location for floating IPs (normally the same as the server location).',
'Type' => 'dropdown',
'Options' => array(),
),
@@ -1082,19 +1136,31 @@ function ArkHostHetznerVPS_ConfigOptions() {
}
}
// Fetch datacenters
$params['action'] = 'Datacenters';
$datacenters = ArkHostHetznerVPS_API($params);
if (isset($datacenters['datacenters'])) {
foreach ($datacenters['datacenters'] as $datacenter) {
$array['datacenter']['Options'] += array(
$datacenter['name'] => $datacenter['description'] . ' (' . $datacenter['location']['city'] . ')'
);
// Also populate floating IP locations
$array['floating_ip_location']['Options'] += array(
$datacenter['location']['name'] => $datacenter['location']['city'] . ', ' . $datacenter['location']['country']
);
// Fetch locations. Hetzner's datacenter endpoints are deprecated
// and are scheduled for removal after 1 October 2026.
$params['action'] = 'Locations';
$locations = ArkHostHetznerVPS_API($params);
if (isset($locations['locations'])) {
foreach ($locations['locations'] as $location) {
if (empty($location['name'])) {
continue;
}
$place = array_filter(array(
$location['city'] ?? '',
$location['country'] ?? ''
));
$description = !empty($location['description'])
? $location['description']
: $location['name'];
$label = $description;
if (!empty($place)) {
$label .= ' (' . implode(', ', $place) . ')';
}
$array['datacenter']['Options'][$location['name']] = $label;
$array['floating_ip_location']['Options'][$location['name']] = $label;
}
}
}
@@ -1218,7 +1284,9 @@ function ArkHostHetznerVPS_CreateAccount(array $params) {
$floatingIpParams = $params;
$floatingIpParams['action'] = 'Create Floating IP';
$floatingIpParams['ip_type'] = $ipType;
$floatingIpParams['location'] = ArkHostHetznerVPS_GetOption($params, 'floating_ip_location');
$floatingIpParams['location'] = ArkHostHetznerVPS_NormalizeLocation(
ArkHostHetznerVPS_GetOption($params, 'floating_ip_location')
);
$floatingIpParams['description'] = 'Server ID: ' . $create['server']['id'];
$floatingIpParams['assign_to_server'] = true;
@@ -1691,8 +1759,9 @@ function ArkHostHetznerVPS_ClientAreaAPI(array $params) {
$createParams = $params;
$createParams['action'] = 'Create Floating IP';
$createParams['ip_type'] = 'ipv4';
$createParams['location'] = ArkHostHetznerVPS_GetOption($params, 'floating_ip_location') ?:
ArkHostHetznerVPS_GetOption($params, 'datacenter');
$createParams['location'] = ArkHostHetznerVPS_NormalizeLocation(
ArkHostHetznerVPS_GetOption($params, 'floating_ip_location')
) ?: ArkHostHetznerVPS_GetLocationOption($params);
$createParams['description'] = 'WHMCS Service ID: ' . $params['serviceid'];
$createParams['assign_to_server'] = true;
@@ -2485,21 +2554,31 @@ function ArkHostHetznerVPS_ClientArea(array $params) {
$serverInfo['bandwidth'] = 20480; // 20TB in GB (20 * 1024)
$serverInfo['bandwidth_used'] = 0; // Not available via API
// Add datacenter info - format as "City, Country"
$city = isset($serverInfo['datacenter']['location']['city']) ? $serverInfo['datacenter']['location']['city'] : '';
$country = isset($serverInfo['datacenter']['location']['country']) ? $serverInfo['datacenter']['location']['country'] : '';
if ($city && $country) {
$serverInfo['datacenter'] = $city . ', ' . $country;
} elseif ($city) {
$serverInfo['datacenter'] = $city;
} elseif ($country) {
$serverInfo['datacenter'] = $country;
} else {
$serverInfo['datacenter'] = 'N/A';
// Hetzner now returns location directly on the server. Retain a fallback
// for cached/older responses that still contain datacenter.location.
$locationInfo = array();
if (isset($serverInfo['location']) && is_array($serverInfo['location'])) {
$locationInfo = $serverInfo['location'];
} elseif (isset($serverInfo['datacenter']['location']) && is_array($serverInfo['datacenter']['location'])) {
$locationInfo = $serverInfo['datacenter']['location'];
}
$serverInfo['location'] = $city ?: 'N/A';
$city = $locationInfo['city'] ?? '';
$country = $locationInfo['country'] ?? '';
if ($city && $country) {
$locationDisplay = $city . ', ' . $country;
} elseif ($city) {
$locationDisplay = $city;
} elseif ($country) {
$locationDisplay = $country;
} else {
$locationDisplay = 'N/A';
}
$serverInfo['location_display'] = $locationDisplay;
// Preserve the former display key for third-party/custom templates.
$serverInfo['datacenter'] = $locationDisplay;
// Get root password with expiration check (72 hours)
$passwordSetTime = $params['model']->serviceProperties->get('ArkHostHetznerVPS|Password Set Time');
+1 -2
View File
@@ -3,7 +3,7 @@
* WHMCS Server Module - Hetzner VPS Hooks
*
* @package WHMCS
* @version 1.2.4
* @version 1.2.5
* @copyright Copyright (c) ArkHost 2025
* @author ArkHost <support@arkhost.com>
* @link https://arkhost.com
@@ -70,4 +70,3 @@ add_hook('ClientAreaHeadOutput', 1, function($vars) {
</style>
HTML;
});
@@ -207,7 +207,7 @@
</tr>
<tr>
<td class="text-muted">{$ADDONLANG.Overview.Location}:</td>
<td><i class="fa fa-map-marker-alt mr-1"></i>{$serverInfo['datacenter']}</td>
<td><i class="fa fa-map-marker-alt mr-1"></i>{$serverInfo['location_display']}</td>
</tr>
<tr>
<td class="text-muted">{$ADDONLANG.Overview.ServerType}:</td>