6 Commits

Author SHA1 Message Date
mariano 0e80c1430f problema gruppo pc 2026-05-20 14:21:18 +02:00
mariano d69c465c92 modifica lista missing computer 2026-05-20 14:17:45 +02:00
mariano aba2ecf4aa modifica visualizzazione pagina server 2026-05-20 14:08:23 +02:00
mariano df28fc0018 sistemazione erore pag server.form.php 2026-05-20 13:48:33 +02:00
mariano 7a578db677 modifica pulsanti comandi 2026-05-20 13:44:44 +02:00
mariano 771409e396 tab in pagina computer.form 2026-05-20 13:39:31 +02:00
3 changed files with 350 additions and 37 deletions
+49 -26
View File
@@ -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));
@@ -27,11 +26,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
ServerAsset::connectAssetToServer($itemtype, $items_id, $server_id);
}
<<<<<<< HEAD
Html::redirect(PLUGIN_URBACKUP_WEB_DIR . '/front/server.form.php?id=' . $server_id);
=======
Html::redirect(PLUGIN_URBACKUP_WEB_DIR . '/front/server.php?id=' . $server_id);
>>>>>>> collegamento_e_verifica_host
}
$id = $_POST['id'] ?? 0;
@@ -56,26 +51,54 @@ Html::header(
'GlpiPlugin\Urbackup\Server'
);
$server->showForm($ID);
if ($ID > 0 && $server->getFromDB($ID)) {
echo '<div class="card mt-4">';
echo '<div class="card-header">';
echo '<h5 class="mb-0">' . htmlspecialchars(__('Linked clients', 'urbackup')) . '</h5>';
echo '</div>';
echo '<div class="card-body">';
Server::showLinkedClientsTab($server);
echo '</div>';
echo '</div>';
echo '<div class="card mt-4">';
echo '<div class="card-header">';
echo '<h5 class="mb-0">' . htmlspecialchars(__('Unlinked clients', 'urbackup')) . '</h5>';
echo '</div>';
echo '<div class="card-body">';
Server::showUnlinkedClientsTab($server);
echo '</div>';
echo '</div>';
if ($ID > 0) {
$server->getFromDB($ID);
?>
<div class="row">
<div class="col-2">
<ul class="nav nav-pills flex-column">
<li class="nav-item">
<a class="nav-link active" data-bs-toggle="tab" href="#tab-server">
<?php echo htmlspecialchars(__('Server')); ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#tab-linked">
<?php echo htmlspecialchars(__('Linked clients', 'urbackup')); ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#tab-unlinked">
<?php echo htmlspecialchars(__('Unlinked clients', 'urbackup')); ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" data-bs-toggle="tab" href="#tab-missing">
<?php echo htmlspecialchars(__('Missing clients', 'urbackup')); ?>
</a>
</li>
</ul>
</div>
<div class="col-10">
<div class="tab-content">
<div class="tab-pane active" id="tab-server">
<?php $server->showForm($ID); ?>
</div>
<div class="tab-pane" id="tab-linked">
<?php Server::showLinkedClientsTab($server); ?>
</div>
<div class="tab-pane" id="tab-unlinked">
<?php Server::showUnlinkedClientsTab($server); ?>
</div>
<div class="tab-pane" id="tab-missing">
<?php Server::showMissingClientsTab($server); ?>
</div>
</div>
</div>
</div>
<?php
} else {
$server->showForm($ID);
}
Html::footer();
Html::footer();
+34 -3
View File
@@ -324,15 +324,36 @@ class AssetTab extends CommonDBTM
): void {
echo "<div class='plugin-urbackup-inner-tabs'>";
echo "<h3>" . htmlspecialchars(__('State', 'urbackup')) . "</h3>";
echo '<ul class="nav nav-tabs" id="urbackupTabs">';
echo '<li class="nav-item">';
echo '<a class="nav-link active" id="state-tab" data-bs-toggle="tab" href="#state" role="tab">';
echo htmlspecialchars(__('State', 'urbackup'));
echo '</a></li>';
echo '<li class="nav-item">';
echo '<a class="nav-link" id="actions-tab" data-bs-toggle="tab" href="#actions" role="tab">';
echo htmlspecialchars(__('Actions', 'urbackup'));
echo '</a></li>';
echo '<li class="nav-item">';
echo '<a class="nav-link" id="logs-tab" data-bs-toggle="tab" href="#logs" role="tab">';
echo htmlspecialchars(__('Info / Log', 'urbackup'));
echo '</a></li>';
echo '</ul>';
echo '<div class="tab-content">';
echo '<div class="tab-pane fade show active" id="state" role="tabpanel">';
self::showStateSection($server, $link, $api_data);
echo '</div>';
echo "<h3>" . htmlspecialchars(__('Actions', 'urbackup')) . "</h3>";
echo '<div class="tab-pane fade" id="actions" role="tabpanel">';
self::showActionsSection($item, $server, $link, $api_data);
echo '</div>';
echo "<h3>" . htmlspecialchars(__('Info / Log', 'urbackup')) . "</h3>";
echo '<div class="tab-pane fade" id="logs" role="tabpanel">';
self::showInfoLogSection($api_data);
echo '</div>';
echo '</div>';
echo "</div>";
}
@@ -465,10 +486,20 @@ class AssetTab extends CommonDBTM
echo "<tr class='tab_bg_1'>";
echo "<td>" . htmlspecialchars(__('Backup commands', 'urbackup')) . "</td>";
echo "<td>";
echo "<div style='display:flex;gap:24px'>";
echo "<div>";
echo "<strong>" . htmlspecialchars(__('File backup', 'urbackup')) . "</strong><br>";
self::showActionButton($item, 'incremental_file_backup', __('Incremental file backup', 'urbackup'), 'btn btn-secondary');
echo "<br>";
self::showActionButton($item, 'full_file_backup', __('Full file backup', 'urbackup'), 'btn btn-secondary');
echo "</div>";
echo "<div>";
echo "<strong>" . htmlspecialchars(__('Image backup', 'urbackup')) . "</strong><br>";
self::showActionButton($item, 'incremental_image_backup', __('Incremental image backup', 'urbackup'), 'btn btn-secondary');
echo "<br>";
self::showActionButton($item, 'full_image_backup', __('Full image backup', 'urbackup'), 'btn btn-secondary');
echo "</div>";
echo "</div>";
echo "</td>";
echo "</tr>";
+267 -8
View File
@@ -12,9 +12,12 @@ use CommonDBTM;
use CommonGLPI;
use Dropdown;
use Entity;
use Group;
use Html;
use Location;
use Session;
use State;
use User;
class Server extends CommonDBTM
{
@@ -324,7 +327,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 "<tr class='tab_bg_1'>";
echo "<td>" . htmlspecialchars(__('Name')) . "</td>";
echo "<td>";
@@ -464,7 +474,7 @@ class Server extends CommonDBTM
echo "</td>";
echo "</tr>";
$apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
$apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
echo "<tr class='tab_bg_1'>";
echo "<td>" . htmlspecialchars(__('API connection status', 'urbackup')) . "<br><small class='text-muted'>" . htmlspecialchars(__('Click Save to test connection', 'urbackup')) . "</small></td>";
echo "<td colspan='3'>";
@@ -479,10 +489,6 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
echo "</td>";
echo "</tr>";
}
$this->showFormButtons($options);
return true;
}
/**
@@ -789,7 +795,6 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
echo '<thead>';
echo '<tr>';
echo '<th>' . htmlspecialchars(__('Asset', 'urbackup')) . '</th>';
echo '<th>' . htmlspecialchars(__('Name', 'urbackup')) . '</th>';
echo '<th>' . htmlspecialchars(__('Client name', 'urbackup')) . '</th>';
echo '<th>' . htmlspecialchars(__('Version', 'urbackup')) . '</th>';
echo '<th>' . htmlspecialchars(__('Status', 'urbackup')) . '</th>';
@@ -840,8 +845,14 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
$itemUrl = $glpiItem ? $glpiItem->getLinkURL() : '';
echo '<tr>';
echo '<td>' . htmlspecialchars($itemTypeLabel . ' #' . $link['items_id']) . '</td>';
echo '<td>' . ($itemUrl ? '<a href="' . htmlspecialchars($itemUrl) . '">' . htmlspecialchars($clientName) . '</a>' : htmlspecialchars($clientName)) . '</td>';
echo '<td>';
if ($itemUrl) {
echo '<a href="' . htmlspecialchars($itemUrl) . '">' . htmlspecialchars($clientName) . '</a>';
} else {
echo htmlspecialchars($clientName);
}
echo ' <small class="text-muted">(' . htmlspecialchars($itemTypeLabel) . ')</small>';
echo '</td>';
echo '<td>' . htmlspecialchars($urbackupClientName) . '</td>';
echo '<td>' . htmlspecialchars($clientVersion) . '</td>';
echo '<td>' . $statusHtml . '</td>';
@@ -1005,4 +1016,252 @@ $apiStatus = (int) ($this->fields['last_api_status'] ?? 0);
echo '</tbody>';
echo '</table>';
}
public static function showMissingClientsTab(Server $server): void
{
global $DB;
$apiStatus = (int) ($server->fields['last_api_status'] ?? 0);
if ($apiStatus !== 1) {
echo '<div class="alert alert-warning">';
echo htmlspecialchars(__('API connection not working. Save server to test connection.', 'urbackup'));
echo '</div>';
return;
}
$serverLocationId = (int) ($server->fields['locations_id'] ?? 0);
if ($serverLocationId <= 0) {
echo '<div class="alert alert-info">';
echo htmlspecialchars(__('No location configured for this server.', 'urbackup'));
echo '</div>';
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 '<div class="alert alert-danger">';
echo htmlspecialchars($e->getMessage());
echo '</div>';
return;
}
$urbackupClientNames = [];
foreach ($urbackupClients as $uc) {
$name = strtolower((string) ($uc['name'] ?? $uc['clientname'] ?? $uc['hostname'] ?? ''));
if ($name !== '') {
$urbackupClientNames[$name] = true;
}
}
$cacheEntity = [];
$cacheLocation = [];
$cacheState = [];
$cacheUser = [];
$cacheGroup = [];
$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'];
$assetId = (int) $assetRow['id'];
if (isset($linkedAssetKeys[$key])) {
continue;
}
if (isset($urbackupClientNames[$nameLower])) {
continue;
}
$entityName = self::getCachedName('Entity', (int) ($assetRow['entities_id'] ?? 0), $cacheEntity);
$locationName = self::getCachedLocationName($assetLocationId, $cacheLocation);
$stateName = self::getCachedName('State', (int) ($assetRow['states_id'] ?? 0), $cacheState);
$userName = self::getCachedName('User', (int) ($assetRow['users_id'] ?? 0), $cacheUser);
$groupName = self::getCachedName('Group', (int) ($assetRow['groups_id'] ?? 0), $cacheGroup);
$ip = self::getAssetIp($itemtype, $assetId);
$missingAssets[] = [
'itemtype' => $itemtype,
'items_id' => $assetId,
'name' => $name,
'entity' => $entityName,
'location' => $locationName,
'otherserial' => (string) ($assetRow['otherserial'] ?? ''),
'ip' => $ip,
'state' => $stateName,
'user' => $userName,
'group' => $groupName,
];
}
}
if (count($missingAssets) === 0) {
echo '<div class="alert alert-success">';
echo htmlspecialchars(__('All assets in this location are linked or already on the UrBackup server.', 'urbackup'));
echo '</div>';
return;
}
$formAction = PLUGIN_URBACKUP_WEB_DIR . '/front/server.form.php';
echo '<table class="table table-striped table-hover">';
echo '<thead><tr>';
echo '<th>' . htmlspecialchars(__('Name')) . '</th>';
echo '<th>' . htmlspecialchars(Entity::getTypeName(1)) . '</th>';
echo '<th>' . htmlspecialchars(Location::getTypeName(1)) . '</th>';
echo '<th>' . htmlspecialchars(__('Inventory number')) . '</th>';
echo '<th>' . htmlspecialchars(__('IP address', 'urbackup')) . '</th>';
echo '<th>' . htmlspecialchars(State::getTypeName(1)) . '</th>';
echo '<th>' . htmlspecialchars(User::getTypeName(1)) . '</th>';
echo '<th>' . htmlspecialchars(Group::getTypeName(1)) . '</th>';
echo '<th>' . htmlspecialchars(__('Actions', 'urbackup')) . '</th>';
echo '</tr></thead>';
echo '<tbody>';
foreach ($missingAssets as $asset) {
echo '<tr>';
echo '<td>' . htmlspecialchars($asset['name']) . '</td>';
echo '<td>' . htmlspecialchars($asset['entity']) . '</td>';
echo '<td>' . htmlspecialchars($asset['location']) . '</td>';
echo '<td>' . htmlspecialchars($asset['otherserial']) . '</td>';
echo '<td>' . htmlspecialchars($asset['ip']) . '</td>';
echo '<td>' . htmlspecialchars($asset['state']) . '</td>';
echo '<td>' . htmlspecialchars($asset['user']) . '</td>';
echo '<td>' . htmlspecialchars($asset['group']) . '</td>';
echo '<td>';
echo '<form method="post" action="' . htmlspecialchars($formAction) . '" class="d-inline">';
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 '<button type="submit" name="link_asset" value="1" class="btn btn-primary btn-sm">';
echo htmlspecialchars(__('Connect'));
echo '</button>';
Html::closeForm();
echo '</td>';
echo '</tr>';
}
echo '</tbody>';
echo '</table>';
}
private static function getCachedName(string $classname, int $id, array &$cache): string
{
if ($id <= 0) {
return '';
}
if (!isset($cache[$id])) {
$fqcn = '\\' . ltrim($classname, '\\');
$obj = new $fqcn();
if ($obj->getFromDB($id)) {
$cache[$id] = (string) ($obj->fields['name'] ?? '');
} else {
$cache[$id] = '';
}
}
return $cache[$id];
}
private static function getCachedLocationName(int $id, array &$cache): string
{
if ($id <= 0) {
return '';
}
if (!isset($cache[$id])) {
$obj = new Location();
if ($obj->getFromDB($id)) {
$cache[$id] = (string) ($obj->fields['completename'] ?? $obj->fields['name'] ?? '');
} else {
$cache[$id] = '';
}
}
return $cache[$id];
}
private static function getAssetIp(string $itemtype, int $items_id): string
{
global $DB;
$iterator = $DB->request([
'SELECT' => ['ipa.name'],
'FROM' => 'glpi_ipaddresses AS ipa',
'INNER JOIN' => [
'glpi_networknames AS nn' => [
'ON' => [
'nn' => 'items_id',
'ipa' => 'id',
['AND' => ['ipa.itemtype' => 'NetworkName']],
],
],
'glpi_networkports AS np' => [
'ON' => [
'np' => 'id',
'nn' => 'items_id',
['AND' => ['nn.itemtype' => 'NetworkPort']],
],
],
],
'WHERE' => [
'np.itemtype' => $itemtype,
'np.items_id' => $items_id,
],
'LIMIT' => 1,
]);
foreach ($iterator as $row) {
$ip = (string) ($row['name'] ?? '');
if ($ip !== '') {
return $ip;
}
}
return '';
}
}