diff --git a/front/server.form.php b/front/server.form.php index ef97b14..b8cade9 100644 --- a/front/server.form.php +++ b/front/server.form.php @@ -3,7 +3,6 @@ use GlpiPlugin\Urbackup\Profile; use GlpiPlugin\Urbackup\Server; use GlpiPlugin\Urbackup\ServerAsset; -use Html; if (!defined('GLPI_ROOT')) { define('GLPI_ROOT', dirname(__DIR__, 4)); @@ -52,26 +51,54 @@ Html::header( 'GlpiPlugin\Urbackup\Server' ); -$server->showForm($ID); - -if ($ID > 0 && $server->getFromDB($ID)) { - echo '
'; - echo '
'; - echo '
' . htmlspecialchars(__('Linked clients', 'urbackup')) . '
'; - echo '
'; - echo '
'; - Server::showLinkedClientsTab($server); - echo '
'; - echo '
'; - - echo '
'; - echo '
'; - echo '
' . htmlspecialchars(__('Unlinked clients', 'urbackup')) . '
'; - echo '
'; - echo '
'; - Server::showUnlinkedClientsTab($server); - echo '
'; - echo '
'; +if ($ID > 0) { + $server->getFromDB($ID); + ?> +
+
+ +
+
+
+
+ showForm($ID); ?> +
+
+ +
+
+ +
+
+ +
+
+
+
+ showForm($ID); } -Html::footer(); \ No newline at end of file +Html::footer(); diff --git a/src/Server.php b/src/Server.php index bf18816..c38392e 100644 --- a/src/Server.php +++ b/src/Server.php @@ -324,7 +324,14 @@ class Server extends CommonDBTM $this->initForm($ID, $options); $this->showFormHeader($options); + $this->showFormFields($ID); + $this->showFormButtons($options); + return true; + } + + public function showFormFields(int $ID): void + { echo ""; echo "" . htmlspecialchars(__('Name')) . ""; echo ""; @@ -464,7 +471,7 @@ class Server extends CommonDBTM echo ""; echo ""; -$apiStatus = (int) ($this->fields['last_api_status'] ?? 0); + $apiStatus = (int) ($this->fields['last_api_status'] ?? 0); echo ""; echo "" . htmlspecialchars(__('API connection status', 'urbackup')) . "
" . htmlspecialchars(__('Click Save to test connection', 'urbackup')) . ""; echo ""; @@ -479,10 +486,6 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0); echo ""; echo ""; } - - $this->showFormButtons($options); - - return true; } /** @@ -789,7 +792,6 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0); echo ''; echo ''; echo '' . htmlspecialchars(__('Asset', 'urbackup')) . ''; - echo '' . htmlspecialchars(__('Name', 'urbackup')) . ''; echo '' . htmlspecialchars(__('Client name', 'urbackup')) . ''; echo '' . htmlspecialchars(__('Version', 'urbackup')) . ''; echo '' . htmlspecialchars(__('Status', 'urbackup')) . ''; @@ -840,8 +842,14 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0); $itemUrl = $glpiItem ? $glpiItem->getLinkURL() : ''; echo ''; - echo '' . htmlspecialchars($itemTypeLabel . ' #' . $link['items_id']) . ''; - echo '' . ($itemUrl ? '' . htmlspecialchars($clientName) . '' : htmlspecialchars($clientName)) . ''; + echo ''; + if ($itemUrl) { + echo '' . htmlspecialchars($clientName) . ''; + } else { + echo htmlspecialchars($clientName); + } + echo ' (' . htmlspecialchars($itemTypeLabel) . ')'; + echo ''; echo '' . htmlspecialchars($urbackupClientName) . ''; echo '' . htmlspecialchars($clientVersion) . ''; echo '' . $statusHtml . ''; @@ -1005,4 +1013,145 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0); echo ''; echo ''; } + + public static function showMissingClientsTab(Server $server): void + { + global $DB; + + $apiStatus = (int) ($server->fields['last_api_status'] ?? 0); + if ($apiStatus !== 1) { + echo '
'; + echo htmlspecialchars(__('API connection not working. Save server to test connection.', 'urbackup')); + echo '
'; + return; + } + + $serverLocationId = (int) ($server->fields['locations_id'] ?? 0); + if ($serverLocationId <= 0) { + echo '
'; + echo htmlspecialchars(__('No location configured for this server.', 'urbackup')); + echo '
'; + return; + } + + $rootLocationId = LocationHelper::getRootLocationId($serverLocationId); + + $linkedIterator = $DB->request([ + 'FROM' => ServerAsset::getTable(), + ]); + $linkedAssetKeys = []; + foreach ($linkedIterator as $row) { + $linkedAssetKeys[$row['itemtype'] . ':' . $row['items_id']] = true; + } + + try { + $client = new UrbackupApiClient($server); + $urbackupClients = $client->getStatus(); + } catch (\Throwable $e) { + echo '
'; + echo htmlspecialchars($e->getMessage()); + echo '
'; + return; + } + + $urbackupClientNames = []; + foreach ($urbackupClients as $uc) { + $name = strtolower((string) ($uc['name'] ?? $uc['clientname'] ?? $uc['hostname'] ?? '')); + if ($name !== '') { + $urbackupClientNames[$name] = true; + } + } + + $itemtypes = Config::getEnabledItemtypes(); + $missingAssets = []; + + foreach ($itemtypes as $itemtype) { + if (!class_exists($itemtype)) { + continue; + } + $assetItem = new $itemtype(); + if (!$assetItem instanceof CommonDBTM) { + continue; + } + $table = $assetItem->getTable(); + if (!$DB->tableExists($table)) { + continue; + } + + $iterator = $DB->request([ + 'FROM' => $table, + 'WHERE' => [ + 'is_deleted' => 0, + ], + ]); + + foreach ($iterator as $assetRow) { + $name = (string) ($assetRow['name'] ?? ''); + if ($name === '') { + continue; + } + $nameLower = strtolower($name); + + $assetLocationId = (int) ($assetRow['locations_id'] ?? 0); + $assetRootLocationId = LocationHelper::getRootLocationId($assetLocationId); + + if ($assetRootLocationId !== $rootLocationId) { + continue; + } + + $key = $itemtype . ':' . $assetRow['id']; + if (isset($linkedAssetKeys[$key])) { + continue; + } + if (isset($urbackupClientNames[$nameLower])) { + continue; + } + + $missingAssets[] = [ + 'itemtype' => $itemtype, + 'items_id' => (int) $assetRow['id'], + 'name' => $name, + ]; + } + } + + if (count($missingAssets) === 0) { + echo '
'; + echo htmlspecialchars(__('All assets in this location are linked or already on the UrBackup server.', 'urbackup')); + echo '
'; + return; + } + + $formAction = PLUGIN_URBACKUP_WEB_DIR . '/front/server.form.php'; + + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + foreach ($missingAssets as $asset) { + $itemtypeLabel = class_exists($asset['itemtype']) ? $asset['itemtype']::getTypeName(1) : $asset['itemtype']; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + echo ''; + echo '
' . htmlspecialchars(__('Asset type')) . '' . htmlspecialchars(__('Name')) . '' . htmlspecialchars(__('Actions', 'urbackup')) . '
' . htmlspecialchars($itemtypeLabel) . '' . htmlspecialchars($asset['name']) . ''; + echo '
'; + echo Html::hidden('_glpi_csrf_token', ['value' => Session::getNewCSRFToken()]); + echo Html::hidden('itemtype', ['value' => $asset['itemtype']]); + echo Html::hidden('items_id', ['value' => $asset['items_id']]); + echo Html::hidden('id', ['value' => (int) $server->fields['id']]); + echo ''; + Html::closeForm(); + echo '
'; + } } \ No newline at end of file