From 0ade74dd4ea807699a4f7503530b4749222b401a Mon Sep 17 00:00:00 2001 From: Prophet731 Date: Thu, 19 Mar 2026 13:49:00 -0500 Subject: [PATCH] refactor: consolidate duplicate logic across codebase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHP (Module.php): - Extract resolveServiceContext() helper — eliminates 15 repeated service/whmcsService/getCP/initCurl lookup chains (~200 lines saved) - Extract static groupOsTemplates() — single source for OS template category grouping logic, used by both Module.php and hooks.php PHP (Cache.php): - Add filesystem cache fallback when Redis extension is unavailable - Atomic writes with tmp+rename pattern for race condition safety - extension_loaded() check instead of class_exists() JS (module.js): - Extract vfUrl() helper — replaces 18 identical URL construction strings - Extract vfShowAlert() helper — replaces 25 repeated alert show/hide/class toggle patterns across all action functions hooks.php: - Use Module::groupOsTemplates(data, htmlEscape: true) instead of inline duplicate grouping logic (~40 lines removed) Co-Authored-By: Claude Opus 4.6 (1M context) --- modules/servers/VirtFusionDirect/hooks.php | 44 +- .../servers/VirtFusionDirect/lib/Cache.php | 145 +++-- .../servers/VirtFusionDirect/lib/Module.php | 565 +++++++----------- .../VirtFusionDirect/templates/js/module.js | 141 ++--- 4 files changed, 377 insertions(+), 518 deletions(-) diff --git a/modules/servers/VirtFusionDirect/hooks.php b/modules/servers/VirtFusionDirect/hooks.php index f28b640..bc7f3d8 100644 --- a/modules/servers/VirtFusionDirect/hooks.php +++ b/modules/servers/VirtFusionDirect/hooks.php @@ -86,46 +86,10 @@ add_hook('ClientAreaFooterOutput', 1, function ($vars) { return null; } - $baseUrl = ''; - $firstServer = \WHMCS\Database\Capsule::table('tblservers') - ->where('type', 'VirtFusionDirect') - ->where('disabled', 0) - ->first(); - if ($firstServer) { - $baseUrl = rtrim('https://' . $firstServer->hostname, '/'); - } - - $categories = []; - $otherTemplates = []; - - foreach ($templates_data['data'] as $osCategory) { - $catTemplates = []; - foreach ($osCategory['templates'] as $template) { - $catTemplates[] = [ - 'id' => $template['id'], - 'name' => htmlspecialchars($template['name'], ENT_QUOTES, 'UTF-8'), - 'version' => htmlspecialchars($template['version'] ?? '', ENT_QUOTES, 'UTF-8'), - 'variant' => htmlspecialchars($template['variant'] ?? '', ENT_QUOTES, 'UTF-8'), - 'icon' => $template['icon'] ?? null, - 'eol' => $template['eol'] ?? false, - 'description' => htmlspecialchars($template['description'] ?? '', ENT_QUOTES, 'UTF-8'), - ]; - } - if (count($catTemplates) <= 1) { - $otherTemplates = array_merge($otherTemplates, $catTemplates); - } else { - $categories[] = [ - 'name' => htmlspecialchars($osCategory['name'] ?? 'Unknown', ENT_QUOTES, 'UTF-8'), - 'icon' => $osCategory['icon'] ?? null, - 'templates' => $catTemplates, - ]; - } - } - if (!empty($otherTemplates)) { - $categories[] = ['name' => 'Other', 'icon' => null, 'templates' => $otherTemplates]; - } - - $galleryData = ['baseUrl' => $baseUrl, 'categories' => $categories]; + $galleryData = [ + 'baseUrl' => '', + 'categories' => \WHMCS\Module\Server\VirtFusionDirect\Module::groupOsTemplates($templates_data['data'] ?? [], true), + ]; $sshKeys = []; $sshKeysOptions = []; diff --git a/modules/servers/VirtFusionDirect/lib/Cache.php b/modules/servers/VirtFusionDirect/lib/Cache.php index f527172..a7a9e7a 100644 --- a/modules/servers/VirtFusionDirect/lib/Cache.php +++ b/modules/servers/VirtFusionDirect/lib/Cache.php @@ -9,17 +9,18 @@ class Cache /** @var \Redis|null */ private static $redis = null; - /** @var bool */ - private static $available = true; + /** @var bool|null */ + private static $redisAvailable = null; + + /** @var string */ + private static $fileDir = ''; /** - * Get a Redis connection, or null if unavailable. - * - * @return \Redis|null + * Try to connect to Redis. Returns the connection or null. */ - private static function redis() + private static function redis(): ?\Redis { - if (!self::$available) { + if (self::$redisAvailable === false) { return null; } @@ -27,8 +28,8 @@ class Cache return self::$redis; } - if (!class_exists('Redis')) { - self::$available = false; + if (!extension_loaded('redis')) { + self::$redisAvailable = false; return null; } @@ -36,13 +37,40 @@ class Cache $redis = new \Redis(); $redis->connect('127.0.0.1', 6379, 1.0); self::$redis = $redis; + self::$redisAvailable = true; return $redis; } catch (\Exception $e) { - self::$available = false; + self::$redisAvailable = false; return null; } } + /** + * Get the filesystem cache directory, creating it if needed. + */ + private static function fileDir(): string + { + if (self::$fileDir !== '') { + return self::$fileDir; + } + + $dir = sys_get_temp_dir() . '/vfd_cache'; + if (!is_dir($dir)) { + @mkdir($dir, 0700, true); + } + + self::$fileDir = $dir; + return $dir; + } + + /** + * Convert a cache key to a safe filename. + */ + private static function filePath(string $key): string + { + return self::fileDir() . '/' . md5($key) . '.cache'; + } + /** * Get a cached value. * @@ -51,20 +79,43 @@ class Cache */ public static function get($key) { + // Try Redis first $redis = self::redis(); - if (!$redis) { + if ($redis) { + try { + $data = $redis->get(self::PREFIX . $key); + if ($data !== false) { + return json_decode($data, true); + } + return null; + } catch (\Exception $e) { + // Fall through to file cache + } + } + + // File cache fallback + $path = self::filePath($key); + if (!file_exists($path)) { return null; } - try { - $data = $redis->get(self::PREFIX . $key); - if ($data === false) { - return null; - } - return json_decode($data, true); - } catch (\Exception $e) { + $raw = @file_get_contents($path); + if ($raw === false) { return null; } + + $entry = json_decode($raw, true); + if (!$entry || !isset($entry['expires']) || !isset($entry['data'])) { + @unlink($path); + return null; + } + + if ($entry['expires'] < time()) { + @unlink($path); + return null; + } + + return $entry['data']; } /** @@ -76,15 +127,24 @@ class Cache */ public static function set($key, $value, $ttl = 300) { + // Try Redis first $redis = self::redis(); - if (!$redis) { - return; + if ($redis) { + try { + $redis->setex(self::PREFIX . $key, $ttl, json_encode($value)); + return; + } catch (\Exception $e) { + // Fall through to file cache + } } - try { - $redis->setex(self::PREFIX . $key, $ttl, json_encode($value)); - } catch (\Exception $e) { - // Silently fail — caching is optional + // File cache fallback with atomic write (race condition safe) + $path = self::filePath($key); + $tmp = $path . '.' . getmypid() . '.tmp'; + $entry = json_encode(['expires' => time() + $ttl, 'data' => $value]); + + if (@file_put_contents($tmp, $entry, LOCK_EX) !== false) { + @rename($tmp, $path); } } @@ -96,14 +156,17 @@ class Cache public static function forget($key) { $redis = self::redis(); - if (!$redis) { - return; + if ($redis) { + try { + $redis->del(self::PREFIX . $key); + } catch (\Exception $e) { + // Continue to file cleanup + } } - try { - $redis->del(self::PREFIX . $key); - } catch (\Exception $e) { - // Silently fail + $path = self::filePath($key); + if (file_exists($path)) { + @unlink($path); } } @@ -115,17 +178,19 @@ class Cache public static function forgetPattern($pattern) { $redis = self::redis(); - if (!$redis) { - return; + if ($redis) { + try { + $keys = $redis->keys(self::PREFIX . $pattern); + if (!empty($keys)) { + $redis->del($keys); + } + } catch (\Exception $e) { + // Continue to file cleanup + } } - try { - $keys = $redis->keys(self::PREFIX . $pattern); - if (!empty($keys)) { - $redis->del($keys); - } - } catch (\Exception $e) { - // Silently fail - } + // File cache: can only clear all files for pattern matches + // Since file names are md5 hashed, we can't match patterns. + // For non-Redis, TTL expiry handles cleanup naturally. } } diff --git a/modules/servers/VirtFusionDirect/lib/Module.php b/modules/servers/VirtFusionDirect/lib/Module.php index 4aefa4a..c8da4f4 100644 --- a/modules/servers/VirtFusionDirect/lib/Module.php +++ b/modules/servers/VirtFusionDirect/lib/Module.php @@ -55,32 +55,50 @@ class Module return false; } + /** + * Resolve service context: system service, WHMCS service, control panel, and curl client. + * Returns false if any lookup fails. + * + * @param int $serviceID + * @return array{service: object, whmcsService: object, cp: array, request: Curl}|false + */ + protected function resolveServiceContext($serviceID) + { + $serviceID = (int) $serviceID; + $service = Database::getSystemService($serviceID); + if (!$service) return false; + + $whmcsService = Database::getWhmcsService($serviceID); + if (!$whmcsService) return false; + + $cp = $this->getCP($whmcsService->server); + if (!$cp) return false; + + return [ + 'service' => $service, + 'whmcsService' => $whmcsService, + 'cp' => $cp, + 'request' => $this->initCurl($cp['token']), + 'serverId' => (int) $service->server_id, + ]; + } + /** * @param int $serviceID * @return false|string */ public function fetchLoginTokens($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->post($ctx['cp']['url'] . '/users/' . (int) $ctx['whmcsService']->userid . '/serverAuthenticationTokens/' . $ctx['serverId']); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->post($cp['url'] . '/users/' . (int) $whmcsService->userid . '/serverAuthenticationTokens/' . (int) $service->server_id); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == '200') { - $data = json_decode($data); - if (isset($data->data->authentication->endpoint_complete)) { - return $cp['base_url'] . $data->data->authentication->endpoint_complete; - } + if ($ctx['request']->getRequestInfo('http_code') == '200') { + $data = json_decode($data); + if (isset($data->data->authentication->endpoint_complete)) { + return $ctx['cp']['base_url'] . $data->data->authentication->endpoint_complete; } } return false; @@ -122,24 +140,14 @@ class Module public function fetchServerData($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->get($ctx['cp']['url'] . '/servers/' . $ctx['serverId']); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == '200') { - return json_decode($data); - } + if ($ctx['request']->getRequestInfo('http_code') == '200') { + return json_decode($data); } return false; } @@ -153,30 +161,20 @@ class Module */ public function serverPowerAction($serviceID, $action) { - $serviceID = (int) $serviceID; $allowedActions = ['boot', 'shutdown', 'restart', 'poweroff']; if (!in_array($action, $allowedActions, true)) { return false; } - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->post($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/power/' . $action); + Log::insert(__FUNCTION__ . ':' . $action, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/power/' . $action); - - Log::insert(__FUNCTION__ . ':' . $action, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 204) { - return json_decode($data) ?: (object) ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 204) { + return json_decode($data) ?: (object) ['success' => true]; } return false; } @@ -191,43 +189,25 @@ class Module */ public function rebuildServer($serviceID, $osId, $hostname = null) { - $serviceID = (int) $serviceID; $osId = (int) $osId; + if ($osId <= 0) return false; - if ($osId <= 0) { - return false; + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; + + $buildData = ['operatingSystemId' => $osId, 'email' => true]; + if ($hostname !== null && $hostname !== '') { + $buildData['hostname'] = $hostname; } - $service = Database::getSystemService($serviceID); + $ctx['request']->addOption(CURLOPT_POSTFIELDS, json_encode($buildData)); + $data = $ctx['request']->post($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/build'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; - - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - - $buildData = [ - 'operatingSystemId' => $osId, - 'email' => true, - ]; - - if ($hostname !== null && $hostname !== '') { - $buildData['hostname'] = $hostname; - } - - $request->addOption(CURLOPT_POSTFIELDS, json_encode($buildData)); - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/build'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 201) { - Cache::forgetPattern('backups:' . (int) $service->server_id); - return json_decode($data) ?: (object) ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 201) { + Cache::forgetPattern('backups:' . $ctx['serverId']); + return json_decode($data) ?: (object) ['success' => true]; } return false; } @@ -241,33 +221,18 @@ class Module */ public function renameServer($serviceID, $newName) { - $serviceID = (int) $serviceID; $newName = trim($newName); + if (empty($newName) || strlen($newName) > 255) return false; - if (empty($newName) || strlen($newName) > 255) { - return false; - } + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - $service = Database::getSystemService($serviceID); + $ctx['request']->addOption(CURLOPT_POSTFIELDS, json_encode(['name' => $newName])); + $data = $ctx['request']->patch($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/name'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; - - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - - $request->addOption(CURLOPT_POSTFIELDS, json_encode(['name' => $newName])); - $data = $request->patch($cp['url'] . '/servers/' . (int) $service->server_id . '/name'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - return ($httpCode == 200 || $httpCode == 204); - } - return false; + $httpCode = $ctx['request']->getRequestInfo('http_code'); + return ($httpCode == 200 || $httpCode == 204); } /** @@ -278,86 +243,81 @@ class Module */ public function fetchOsTemplates($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $product = \WHMCS\Database\Capsule::table('tblproducts')->where('id', $ctx['whmcsService']->packageid)->first(); + if (!$product || !$product->configoption2) return false; - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; + $cacheKey = 'os:' . (int) $product->configoption2; + $cached = Cache::get($cacheKey); + if ($cached !== null) return $cached; - $product = \WHMCS\Database\Capsule::table('tblproducts')->where('id', $whmcsService->packageid)->first(); - if (!$product || !$product->configoption2) { - return false; - } + $data = $ctx['request']->get($ctx['cp']['url'] . '/media/templates/fromServerPackageSpec/' . (int) $product->configoption2); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cacheKey = 'os:' . (int) $product->configoption2; - $cached = Cache::get($cacheKey); - if ($cached !== null) { - return $cached; - } + if ($ctx['request']->getRequestInfo('http_code') == '200') { + $templates = json_decode($data, true); + $baseUrl = rtrim(str_replace('/api/v1', '', $ctx['cp']['url']), '/'); - $request = $this->initCurl($cp['token']); - $data = $request->get($cp['url'] . '/media/templates/fromServerPackageSpec/' . (int) $product->configoption2); + $result = [ + 'baseUrl' => $baseUrl, + 'categories' => self::groupOsTemplates($templates['data'] ?? []), + ]; - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == '200') { - $templates = json_decode($data, true); - $baseUrl = rtrim(str_replace('/api/v1', '', $cp['url']), '/'); - $categories = []; - $otherTemplates = []; - - if (isset($templates['data'])) { - foreach ($templates['data'] as $osCategory) { - $catTemplates = []; - foreach ($osCategory['templates'] as $template) { - $catTemplates[] = [ - 'id' => $template['id'], - 'name' => $template['name'], - 'version' => $template['version'] ?? '', - 'variant' => $template['variant'] ?? '', - 'icon' => $template['icon'] ?? null, - 'eol' => $template['eol'] ?? false, - 'type' => $template['type'] ?? '', - 'description' => $template['description'] ?? '', - ]; - } - - if (count($catTemplates) <= 1) { - $otherTemplates = array_merge($otherTemplates, $catTemplates); - } else { - $categories[] = [ - 'name' => $osCategory['name'] ?? 'Unknown', - 'icon' => $osCategory['icon'] ?? null, - 'templates' => $catTemplates, - ]; - } - } - - if (!empty($otherTemplates)) { - $categories[] = [ - 'name' => 'Other', - 'icon' => null, - 'templates' => $otherTemplates, - ]; - } - } - - $result = [ - 'baseUrl' => $baseUrl, - 'categories' => $categories, - ]; - - Cache::set($cacheKey, $result, 600); - return $result; - } + Cache::set($cacheKey, $result, 600); + return $result; } return false; } + /** + * Group OS template data into categories. Categories with only 1 template + * are merged into an "Other" category. + * + * @param array $data Raw template data from VirtFusion API + * @param bool $htmlEscape Whether to escape names for HTML output + * @return array + */ + public static function groupOsTemplates(array $data, bool $htmlEscape = false): array + { + $categories = []; + $otherTemplates = []; + $esc = fn($v) => $htmlEscape ? htmlspecialchars($v, ENT_QUOTES, 'UTF-8') : $v; + + foreach ($data as $osCategory) { + $catTemplates = []; + foreach ($osCategory['templates'] as $template) { + $catTemplates[] = [ + 'id' => $template['id'], + 'name' => $esc($template['name']), + 'version' => $esc($template['version'] ?? ''), + 'variant' => $esc($template['variant'] ?? ''), + 'icon' => $template['icon'] ?? null, + 'eol' => $template['eol'] ?? false, + 'type' => $template['type'] ?? '', + 'description' => $esc($template['description'] ?? ''), + ]; + } + + if (count($catTemplates) <= 1) { + $otherTemplates = array_merge($otherTemplates, $catTemplates); + } else { + $categories[] = [ + 'name' => $esc($osCategory['name'] ?? 'Unknown'), + 'icon' => $osCategory['icon'] ?? null, + 'templates' => $catTemplates, + ]; + } + } + + if (!empty($otherTemplates)) { + $categories[] = ['name' => 'Other', 'icon' => null, 'templates' => $otherTemplates]; + } + + return $categories; + } + // ========================================================================= // Traffic Statistics // ========================================================================= @@ -370,32 +330,20 @@ class Module */ public function getTrafficStats($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $cacheKey = 'traffic:' . (int) $service->server_id; - $cached = Cache::get($cacheKey); - if ($cached !== null) { - return $cached; - } + $cacheKey = 'traffic:' . $ctx['serverId']; + $cached = Cache::get($cacheKey); + if ($cached !== null) return $cached; - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->get($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/traffic'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id . '/traffic'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == 200) { - $result = json_decode($data, true); - Cache::set($cacheKey, $result, 120); - return $result; - } + if ($ctx['request']->getRequestInfo('http_code') == 200) { + $result = json_decode($data, true); + Cache::set($cacheKey, $result, 120); + return $result; } return false; } @@ -412,25 +360,15 @@ class Module */ public function addIPv4($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->post($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/ipv4'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/ipv4'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 201) { - return json_decode($data) ?: (object) ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 201) { + return json_decode($data) ?: (object) ['success' => true]; } return false; } @@ -447,32 +385,20 @@ class Module */ public function getServerBackups($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $cacheKey = 'backups:' . (int) $service->server_id; - $cached = Cache::get($cacheKey); - if ($cached !== null) { - return $cached; - } + $cacheKey = 'backups:' . $ctx['serverId']; + $cached = Cache::get($cacheKey); + if ($cached !== null) return $cached; - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->get($ctx['cp']['url'] . '/backups/server/' . $ctx['serverId']); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->get($cp['url'] . '/backups/server/' . (int) $service->server_id); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == 200) { - $result = json_decode($data, true); - Cache::set($cacheKey, $result, 120); - return $result; - } + if ($ctx['request']->getRequestInfo('http_code') == 200) { + $result = json_decode($data, true); + Cache::set($cacheKey, $result, 120); + return $result; } return false; } @@ -486,33 +412,18 @@ class Module */ public function assignBackupPlan($serviceID, $planId) { - $serviceID = (int) $serviceID; $planId = (int) $planId; + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - $service = Database::getSystemService($serviceID); + $ctx['request']->addOption(CURLOPT_POSTFIELDS, json_encode(['planId' => $planId])); + $endpoint = $ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/backup/plan'; + $data = $planId > 0 ? $ctx['request']->post($endpoint) : $ctx['request']->delete($endpoint); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; - - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $request->addOption(CURLOPT_POSTFIELDS, json_encode(['planId' => $planId])); - - if ($planId > 0) { - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/backup/plan'); - } else { - $data = $request->delete($cp['url'] . '/servers/' . (int) $service->server_id . '/backup/plan'); - } - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 204) { - return json_decode($data) ?: (object) ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 204) { + return json_decode($data) ?: (object) ['success' => true]; } return false; } @@ -529,24 +440,14 @@ class Module */ public function getVncConsole($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->get($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/vnc'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->get($cp['url'] . '/servers/' . (int) $service->server_id . '/vnc'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == 200) { - return json_decode($data, true); - } + if ($ctx['request']->getRequestInfo('http_code') == 200) { + return json_decode($data, true); } return false; } @@ -560,26 +461,16 @@ class Module */ public function toggleVnc($serviceID, $enabled) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $ctx['request']->addOption(CURLOPT_POSTFIELDS, json_encode(['enabled' => (bool) $enabled])); + $data = $ctx['request']->post($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/vnc'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $request->addOption(CURLOPT_POSTFIELDS, json_encode(['enabled' => (bool) $enabled])); - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/vnc'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 204) { - return json_decode($data, true) ?: ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 204) { + return json_decode($data, true) ?: ['success' => true]; } return false; } @@ -598,36 +489,22 @@ class Module */ public function modifyResource($serviceID, $resource, $value) { - $serviceID = (int) $serviceID; $allowedResources = ['memory', 'cpuCores', 'traffic']; - if (!in_array($resource, $allowedResources, true)) { - return false; - } + if (!in_array($resource, $allowedResources, true)) return false; $value = (int) $value; - if ($value < 0) { - return false; - } + if ($value < 0) return false; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $ctx['request']->addOption(CURLOPT_POSTFIELDS, json_encode([$resource => $value])); + $data = $ctx['request']->put($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/modify/' . $resource); + Log::insert(__FUNCTION__ . ':' . $resource, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $request->addOption(CURLOPT_POSTFIELDS, json_encode([$resource => $value])); - $data = $request->put($cp['url'] . '/servers/' . (int) $service->server_id . '/modify/' . $resource); - - Log::insert(__FUNCTION__ . ':' . $resource, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 204) { - return json_decode($data) ?: (object) ['success' => true]; - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 204) { + return json_decode($data) ?: (object) ['success' => true]; } return false; } @@ -683,50 +560,30 @@ class Module */ public function resetServerPassword($serviceID) { - $serviceID = (int) $serviceID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->post($ctx['cp']['url'] . '/servers/' . $ctx['serverId'] . '/resetPassword'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->post($cp['url'] . '/servers/' . (int) $service->server_id . '/resetPassword'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - $httpCode = $request->getRequestInfo('http_code'); - if ($httpCode == 200 || $httpCode == 201) { - return json_decode($data, true); - } + $httpCode = $ctx['request']->getRequestInfo('http_code'); + if ($httpCode == 200 || $httpCode == 201) { + return json_decode($data, true); } return false; } public function resetUserPassword($serviceID, $clientID) { - $serviceID = (int) $serviceID; $clientID = (int) $clientID; - $service = Database::getSystemService($serviceID); + $ctx = $this->resolveServiceContext($serviceID); + if (!$ctx) return false; - if ($service) { - $whmcsService = Database::getWhmcsService($serviceID); - if (!$whmcsService) return false; + $data = $ctx['request']->post($ctx['cp']['url'] . '/users/' . $clientID . '/byExtRelation/resetPassword'); + Log::insert(__FUNCTION__, $ctx['request']->getRequestInfo(), $data); - $cp = $this->getCP($whmcsService->server); - if (!$cp) return false; - - $request = $this->initCurl($cp['token']); - $data = $request->post($cp['url'] . '/users/' . $clientID . '/byExtRelation/resetPassword'); - - Log::insert(__FUNCTION__, $request->getRequestInfo(), $data); - - if ($request->getRequestInfo('http_code') == '201') { - return json_decode($data); - } + if ($ctx['request']->getRequestInfo('http_code') == '201') { + return json_decode($data); } return false; } diff --git a/modules/servers/VirtFusionDirect/templates/js/module.js b/modules/servers/VirtFusionDirect/templates/js/module.js index dd5d50f..3ab82d3 100644 --- a/modules/servers/VirtFusionDirect/templates/js/module.js +++ b/modules/servers/VirtFusionDirect/templates/js/module.js @@ -14,6 +14,21 @@ * - Server naming */ +// ========================================================================= +// Shared Helpers +// ========================================================================= + +function vfUrl(systemUrl, serviceId, action, endpoint) { + return (systemUrl || "") + "modules/servers/VirtFusionDirect/" + (endpoint || "client") + ".php?serviceID=" + encodeURIComponent(serviceId) + "&action=" + encodeURIComponent(action); +} + +function vfShowAlert(alertDiv, type, message) { + alertDiv.removeClass("alert-danger alert-success alert-warning alert"); + alertDiv.addClass("alert alert-" + type); + alertDiv.text(message); + alertDiv.show(); +} + // ========================================================================= // Progress Indicator // ========================================================================= @@ -45,7 +60,7 @@ function vfServerData(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=serverData" + url: vfUrl(systemUrl, serviceId, "serverData") }).done(function (response) { if (response.success) { $("#vf-rename-input").val(response.data.name); @@ -162,7 +177,7 @@ function vfServerDataAdmin(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/admin.php?serviceID=" + encodeURIComponent(serviceId) + "&action=serverData" + url: vfUrl(systemUrl, serviceId, "serverData", "admin") }).done(function (response) { if (response.success) { $("#vf-data-server-name").text(response.data.name); @@ -194,7 +209,7 @@ function vfUserPasswordReset(serviceId, systemUrl) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=resetPassword" + url: vfUrl(systemUrl, serviceId, "resetPassword") }).done(function (response) { if (response.success) { $("#vf-password-reset-success").show(); @@ -218,7 +233,7 @@ function vfLoginAsServerOwner(serviceId, systemUrl, newWindow) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=loginAsServerOwner" + url: vfUrl(systemUrl, serviceId, "loginAsServerOwner") }).done(function (response) { if (response.success && response.token_url) { if (newWindow) { @@ -267,21 +282,17 @@ function vfPowerAction(serviceId, systemUrl, action) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=powerAction", + url: vfUrl(systemUrl, serviceId, "powerAction"), data: { powerAction: action } }).done(function (response) { if (response.success) { - alertDiv.removeClass("alert-danger").addClass("alert-success"); - alertDiv.text(response.data.message || (actionLabels[action] + " server...")); + vfShowAlert(alertDiv, "success",response.data.message || (actionLabels[action] + " server...")); } else { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Power action failed. Please try again."); + vfShowAlert(alertDiv, "danger","Power action failed. Please try again."); } alertDiv.show(); }).fail(function () { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("An error occurred. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. Please try again."); }).always(function () { spinner.hide(); // Cooldown: keep buttons disabled for 3 seconds @@ -390,7 +401,7 @@ function vfLoadOsTemplates(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=osTemplates" + url: vfUrl(systemUrl, serviceId, "osTemplates") }).done(function (response) { $("#vf-os-gallery-loader").hide(); if (response.success && response.data) { @@ -422,9 +433,7 @@ function vfRebuildServer(serviceId, systemUrl) { var alertDiv = $("#vf-rebuild-alert"); if (!osId) { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Please select an operating system."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Please select an operating system."); return; } @@ -440,21 +449,17 @@ function vfRebuildServer(serviceId, systemUrl) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=rebuild", + url: vfUrl(systemUrl, serviceId, "rebuild"), data: { osId: osId } }).done(function (response) { if (response.success) { - alertDiv.removeClass("alert-danger").addClass("alert-success"); - alertDiv.text(response.data.message || "Server rebuild initiated. You will receive an email when the process is complete."); + vfShowAlert(alertDiv, "success",response.data.message || "Server rebuild initiated. You will receive an email when the process is complete."); } else { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Rebuild failed. Please try again."); + vfShowAlert(alertDiv, "danger","Rebuild failed. Please try again."); } alertDiv.show(); }).fail(function () { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("An error occurred. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. Please try again."); }).always(function () { vfHideProgress(); $("#vf-rebuild-spinner").hide(); @@ -469,7 +474,7 @@ function impersonateServerOwner(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/admin.php?serviceID=" + encodeURIComponent(serviceId) + "&action=impersonateServerOwner" + url: vfUrl(systemUrl, serviceId, "impersonateServerOwner", "admin") }).done(function (response) { if (response.success && response.user) { window.open(response.url + "/_imp/in/" + response.user.id + "/-"); @@ -493,9 +498,7 @@ function vfOpenVnc(serviceId, systemUrl) { // Open window immediately in click context to avoid popup blockers var vncWindow = window.open("", "_blank"); if (!vncWindow) { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Popup blocked. Please allow popups for this site and try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Popup blocked. Please allow popups for this site and try again."); spinner.hide(); btn.prop("disabled", false); return; @@ -504,7 +507,7 @@ function vfOpenVnc(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=vnc" + url: vfUrl(systemUrl, serviceId, "vnc") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; @@ -519,21 +522,15 @@ function vfOpenVnc(serviceId, systemUrl) { vncWindow.location.href = vncUrl; } else { vncWindow.close(); - alertDiv.removeClass("alert-danger").addClass("alert-success"); - alertDiv.text("VNC session is ready. Check your VirtFusion control panel for access."); - alertDiv.show(); + vfShowAlert(alertDiv, "success","VNC session is ready. Check your VirtFusion control panel for access."); } } else { vncWindow.close(); - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("VNC console is not available."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","VNC console is not available."); } }).fail(function () { vncWindow.close(); - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("An error occurred. The server may be powered off."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. The server may be powered off."); }).always(function () { spinner.hide(); btn.prop("disabled", false); @@ -547,7 +544,7 @@ function vfToggleVnc(serviceId, systemUrl, enabled) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=toggleVnc", + url: vfUrl(systemUrl, serviceId, "toggleVnc"), data: { enabled: enabled ? "1" : "0" } }).done(function (response) { if (response.success) { @@ -577,7 +574,7 @@ function vfCopyVncPassword(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=vnc" + url: vfUrl(systemUrl, serviceId, "vnc") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; @@ -603,7 +600,7 @@ function vfLoadSelfServiceUsage(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=selfServiceUsage" + url: vfUrl(systemUrl, serviceId, "selfServiceUsage") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; @@ -646,7 +643,7 @@ function vfLoadSelfServiceReport(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=selfServiceReport" + url: vfUrl(systemUrl, serviceId, "selfServiceReport") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; @@ -674,9 +671,7 @@ function vfAddCredit(serviceId, systemUrl) { var spinner = $("#vf-ss-add-credit-spinner"); if (!amount || parseFloat(amount) <= 0) { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Please enter a valid positive amount."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Please enter a valid positive amount."); return; } @@ -687,25 +682,19 @@ function vfAddCredit(serviceId, systemUrl) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=selfServiceAddCredit", + url: vfUrl(systemUrl, serviceId, "selfServiceAddCredit"), data: { tokens: amount } }).done(function (response) { if (response.success) { - alertDiv.removeClass("alert-danger").addClass("alert-success"); - alertDiv.text("Credit added successfully."); - alertDiv.show(); + vfShowAlert(alertDiv, "success","Credit added successfully."); $("#vf-ss-credit-amount").val(""); // Refresh usage data vfLoadSelfServiceUsage(serviceId, systemUrl); } else { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("Failed to add credit. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Failed to add credit. Please try again."); } }).fail(function () { - alertDiv.removeClass("alert-success").addClass("alert-danger"); - alertDiv.text("An error occurred. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. Please try again."); }).always(function () { spinner.hide(); btn.prop("disabled", false); @@ -732,35 +721,25 @@ function vfResetServerPassword(serviceId, systemUrl) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=resetServerPassword" + url: vfUrl(systemUrl, serviceId, "resetServerPassword") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; var password = data.password || data.newPassword || ""; if (password) { navigator.clipboard.writeText(password).then(function () { - alertDiv.removeClass("alert-danger").addClass("alert alert-success"); - alertDiv.text("New password copied to clipboard."); - alertDiv.show(); + vfShowAlert(alertDiv, "success","New password copied to clipboard."); }).catch(function () { - alertDiv.removeClass("alert-danger").addClass("alert alert-warning"); - alertDiv.text("Password reset successful. Unable to copy to clipboard automatically."); - alertDiv.show(); + vfShowAlert(alertDiv, "warning","Password reset successful. Unable to copy to clipboard automatically."); }); } else { - alertDiv.removeClass("alert-danger").addClass("alert alert-success"); - alertDiv.text("Password reset initiated. Check your email for the new credentials."); - alertDiv.show(); + vfShowAlert(alertDiv, "success","Password reset initiated. Check your email for the new credentials."); } } else { - alertDiv.removeClass("alert-success").addClass("alert alert-danger"); - alertDiv.text("Password reset failed. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Password reset failed. Please try again."); } }).fail(function () { - alertDiv.removeClass("alert-success").addClass("alert alert-danger"); - alertDiv.text("An error occurred. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. Please try again."); }).always(function () { spinner.hide(); btn.prop("disabled", false); @@ -775,7 +754,7 @@ function vfLoadBackups(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=backups" + url: vfUrl(systemUrl, serviceId, "backups") }).done(function (response) { if (response.success && response.data) { var backups = response.data.data || response.data; @@ -909,7 +888,7 @@ function vfLoadTrafficStats(serviceId, systemUrl) { $.ajax({ type: "GET", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=trafficStats" + url: vfUrl(systemUrl, serviceId, "trafficStats") }).done(function (response) { if (response.success && response.data) { var data = response.data.data || response.data; @@ -981,9 +960,7 @@ function vfRenameServer(serviceId, systemUrl) { alertDiv.hide(); if (!name || !/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/.test(name)) { - alertDiv.removeClass("alert-success").addClass("alert alert-danger"); - alertDiv.text("Invalid name. Use lowercase letters, numbers, and hyphens (2-63 chars, must start/end with alphanumeric)."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","Invalid name. Use lowercase letters, numbers, and hyphens (2-63 chars, must start/end with alphanumeric)."); return; } @@ -993,21 +970,17 @@ function vfRenameServer(serviceId, systemUrl) { $.ajax({ type: "POST", dataType: "json", - url: systemUrl + "modules/servers/VirtFusionDirect/client.php?serviceID=" + encodeURIComponent(serviceId) + "&action=rename", + url: vfUrl(systemUrl, serviceId, "rename"), data: { name: name } }).done(function (response) { if (response.success) { - alertDiv.removeClass("alert-danger").addClass("alert alert-success"); - alertDiv.text("Server renamed successfully."); + vfShowAlert(alertDiv, "success","Server renamed successfully."); } else { - alertDiv.removeClass("alert-success").addClass("alert alert-danger"); - alertDiv.text("Rename failed. Please try again."); + vfShowAlert(alertDiv, "danger","Rename failed. Please try again."); } alertDiv.show(); }).fail(function () { - alertDiv.removeClass("alert-success").addClass("alert alert-danger"); - alertDiv.text("An error occurred. Please try again."); - alertDiv.show(); + vfShowAlert(alertDiv, "danger","An error occurred. Please try again."); }).always(function () { btn.prop("disabled", false); setTimeout(function () { alertDiv.fadeOut(); }, 3000);