sistemazione finale - server .php
This commit is contained in:
@@ -267,3 +267,51 @@ Il test del pulsante "Test API" continua a restituire 403 Forbidden quando acces
|
||||
- `src/AssetTab.php`: Aggiunti metodi `startBackup()`, `saveInternetMode()`, `saveDefaultDirs()`
|
||||
- `src/UrbackupApiClient.php`: Aggiunti metodi `updateClientSettings()`, `saveInternetMode()`
|
||||
- `front/asset.form.php`: Gestione azioni per salvataggio impostazioni e backup
|
||||
|
||||
### Refactoring server.form.php e nuove tab (v0.4.7)
|
||||
|
||||
**Data**: 2026-05-21
|
||||
|
||||
**Descrizione**: Restrutturazione completa della pagina server con tab laterali e nuove funzionalità:
|
||||
|
||||
**Refactoring Server::showForm()**:
|
||||
- Estratto `showFormFields(?int $ID)` da `showForm()` per permettere layout custom
|
||||
- `showForm()` ora chiama header + fields + buttons in sequenza
|
||||
|
||||
**Tab laterali (server.form.php)**:
|
||||
- Side tabs a sinistra (col-2) con `nav-pills flex-column`
|
||||
- 4 tab: Server, Linked clients, Unlinked clients, Missing clients
|
||||
- Tab persistence via URL hash (JS su `shown.bs.tab`)
|
||||
|
||||
**Missing clients tab**:
|
||||
- Mostra asset GLPI con root location matching, non ancora collegati a ServerAsset e non presenti su UrBackup
|
||||
- Colonne: Name (link all'asset), Entity, Location (completename), Inventory number, IP, State, User, Group
|
||||
- Ricerca testuale client-side
|
||||
- Ordinamento colonne click-to-sort vanilla JS
|
||||
- Navigazione server spostata in server.form.php (sopra i tab, indipendente dalle sezioni)
|
||||
|
||||
**Bug fix namespace risolto**:
|
||||
- `getCachedName()` usava `new $classname()` con stringa → PHP cercava `GlpiPlugin\Urbackup\Group` invece di `\Group`
|
||||
- Fix: `$fqcn = '\\' . ltrim($classname, '\\')` per forzare global namespace
|
||||
|
||||
**Gruppo asset corretto**:
|
||||
- Gruppo non in `glpi_computers.groups_id` (colonna inesistente)
|
||||
- Letto da `glpi_groups_items` WHERE `type = 1` (GROUP_TYPE_NORMAL)
|
||||
- Usa `completename` per gerarchia (es. "Helpdesk > Livello 1")
|
||||
|
||||
**Indirizzo IP asset**:
|
||||
- Query JOIN: `glpi_ipaddresses → glpi_networknames → glpi_networkports`
|
||||
- Primo IP valido per l'item
|
||||
|
||||
**Breadcrumb**:
|
||||
- Cambiato da `'Assets'` a `'admin'` in `Html::header()` di server.php e server.form.php
|
||||
- Mostra: Pagina principale > Amministrazione > UrBackup servers
|
||||
|
||||
**Fix port default per nuovi server**:
|
||||
- `prepareInputForAdd()` ora setta default 55414 per `port`, 'http' per `protocol`, 1 per `is_active`, ecc.
|
||||
- `prepareInputForUpdate()` normalizza anche valori vuoti
|
||||
|
||||
**File modificati**:
|
||||
- `src/Server.php`: `showFormFields()`, `showMissingClientsTab()`, `getCachedName()` fix, `getAssetGroupName()`, `getAssetIp()`, `getCachedLocationName()`, `prepareInputForAdd/Update` default fix
|
||||
- `front/server.form.php`: Tab laterali, tab hash JS, breadcrumb admin
|
||||
- `front/server.php`: Breadcrumb admin, rimosso pulsante "Add" manuale (GLPI lo genera)
|
||||
|
||||
+63
-1
@@ -47,13 +47,62 @@ $ID = $_GET['id'] ?? null;
|
||||
Html::header(
|
||||
$ID ? __('Edit UrBackup server', 'urbackup') : __('Add UrBackup server', 'urbackup'),
|
||||
'',
|
||||
'Assets',
|
||||
'admin',
|
||||
'GlpiPlugin\Urbackup\Server'
|
||||
);
|
||||
|
||||
if ($ID > 0) {
|
||||
global $DB;
|
||||
|
||||
$server->getFromDB($ID);
|
||||
|
||||
$serverIterator = $DB->request([
|
||||
'FROM' => Server::getTable(),
|
||||
'ORDER' => 'name',
|
||||
]);
|
||||
$serverIds = [];
|
||||
foreach ($serverIterator as $row) {
|
||||
$serverIds[(int) $row['id']] = (string) $row['name'];
|
||||
}
|
||||
$serverIdKeys = array_keys($serverIds);
|
||||
$currentIndex = array_search((int) $ID, $serverIdKeys, true);
|
||||
$totalServers = count($serverIds);
|
||||
$prevId = ($currentIndex !== false && $currentIndex > 0) ? $serverIdKeys[$currentIndex - 1] : null;
|
||||
$nextId = ($currentIndex !== false && $currentIndex < $totalServers - 1) ? $serverIdKeys[$currentIndex + 1] : null;
|
||||
|
||||
$baseUrl = PLUGIN_URBACKUP_WEB_DIR . '/front/server.form.php';
|
||||
?>
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="<?php echo htmlspecialchars(PLUGIN_URBACKUP_WEB_DIR . '/front/server.php'); ?>" class="btn btn-sm btn-icon btn-ghost-secondary me-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" title="<?php echo htmlspecialchars(__('List')); ?>">
|
||||
<i class="ti ti-list-search fs-2"></i>
|
||||
</a>
|
||||
<?php if ($prevId !== null): ?>
|
||||
<a href="<?php echo htmlspecialchars($baseUrl . '?id=' . $prevId); ?>"
|
||||
class="btn btn-sm btn-icon btn-ghost-secondary me-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" title="<?php echo htmlspecialchars(__('Previous')); ?>">
|
||||
<i class="fs-2 ti ti-chevron-left"></i>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="btn btn-sm btn-icon btn-ghost-secondary me-2 bs-invisible">
|
||||
<i class="fs-2 ti ti-chevron-left"></i>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<span class="fw-bold mx-2"><?php echo htmlspecialchars(($currentIndex !== false ? $currentIndex + 1 : 1) . ' / ' . $totalServers); ?></span>
|
||||
<?php if ($nextId !== null): ?>
|
||||
<a href="<?php echo htmlspecialchars($baseUrl . '?id=' . $nextId); ?>"
|
||||
class="btn btn-sm btn-icon btn-ghost-secondary ms-2"
|
||||
data-bs-toggle="tooltip" data-bs-placement="bottom" title="<?php echo htmlspecialchars(__('Next')); ?>">
|
||||
<i class="fs-2 ti ti-chevron-right"></i>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span class="btn btn-sm btn-icon btn-ghost-secondary ms-2 bs-invisible">
|
||||
<i class="fs-2 ti ti-chevron-right"></i>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<ul class="nav nav-pills flex-column">
|
||||
@@ -101,4 +150,17 @@ if ($ID > 0) {
|
||||
$server->showForm($ID);
|
||||
}
|
||||
|
||||
?>
|
||||
<script>
|
||||
$(function () {
|
||||
var hash = window.location.hash;
|
||||
if (hash) {
|
||||
$('[data-bs-toggle="tab"][href="' + hash + '"]').tab('show');
|
||||
}
|
||||
$('[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
window.location.hash = $(this).attr('href');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
Html::footer();
|
||||
|
||||
+3
-17
@@ -15,27 +15,13 @@ if (!Profile::canCurrentUser(READ)) {
|
||||
Html::displayRightError();
|
||||
}
|
||||
|
||||
$can_read = Profile::canCurrentUser(READ);
|
||||
$can_create = Profile::canCurrentUser(CREATE);
|
||||
|
||||
Html::header(
|
||||
'UrBackup Servers',
|
||||
'',
|
||||
'Assets',
|
||||
''
|
||||
'admin',
|
||||
'GlpiPlugin\Urbackup\Server'
|
||||
);
|
||||
|
||||
if ($can_create) {
|
||||
echo "<div class='center'>";
|
||||
echo Html::link(
|
||||
__('Add UrBackup server', 'urbackup'),
|
||||
'/plugins/urbackup/front/server.form.php',
|
||||
['class' => 'btn btn-primary']
|
||||
);
|
||||
echo "</div>";
|
||||
echo "<br>";
|
||||
}
|
||||
|
||||
Search::show('GlpiPlugin\Urbackup\Server', [
|
||||
'is_deleted' => 0,
|
||||
'massiveaction' => true,
|
||||
@@ -45,4 +31,4 @@ Search::show('GlpiPlugin\Urbackup\Server', [
|
||||
],
|
||||
]);
|
||||
|
||||
Html::footer();
|
||||
Html::footer();
|
||||
|
||||
+103
-13
@@ -333,7 +333,7 @@ class Server extends CommonDBTM
|
||||
return true;
|
||||
}
|
||||
|
||||
public function showFormFields(int $ID): void
|
||||
public function showFormFields(?int $ID): void
|
||||
{
|
||||
echo "<tr class='tab_bg_1'>";
|
||||
echo "<td>" . htmlspecialchars(__('Name')) . "</td>";
|
||||
@@ -548,6 +548,26 @@ class Server extends CommonDBTM
|
||||
|
||||
public function prepareInputForAdd(mixed $input): mixed
|
||||
{
|
||||
if (!is_array($input)) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
if (!isset($input['port']) || $input['port'] === '' || $input['port'] === null) {
|
||||
$input['port'] = 55414;
|
||||
}
|
||||
if (!isset($input['protocol']) || $input['protocol'] === '') {
|
||||
$input['protocol'] = 'http';
|
||||
}
|
||||
if (!isset($input['is_active']) || $input['is_active'] === '' || $input['is_active'] === null) {
|
||||
$input['is_active'] = 1;
|
||||
}
|
||||
if (!isset($input['is_recursive']) || $input['is_recursive'] === '' || $input['is_recursive'] === null) {
|
||||
$input['is_recursive'] = 0;
|
||||
}
|
||||
if (!isset($input['ignore_ssl']) || $input['ignore_ssl'] === '' || $input['ignore_ssl'] === null) {
|
||||
$input['ignore_ssl'] = 0;
|
||||
}
|
||||
|
||||
return $this->prepareInputForUpdate($input);
|
||||
}
|
||||
|
||||
@@ -557,6 +577,16 @@ class Server extends CommonDBTM
|
||||
return $input;
|
||||
}
|
||||
|
||||
if (isset($input['port']) && ($input['port'] === '' || $input['port'] === null)) {
|
||||
$input['port'] = 55414;
|
||||
}
|
||||
if (isset($input['protocol']) && $input['protocol'] === '') {
|
||||
$input['protocol'] = 'http';
|
||||
}
|
||||
if (isset($input['ignore_ssl']) && ($input['ignore_ssl'] === '' || $input['ignore_ssl'] === null)) {
|
||||
$input['ignore_ssl'] = 0;
|
||||
}
|
||||
|
||||
if (!empty($input['id']) && (int) $input['id'] > 0) {
|
||||
$server = new self();
|
||||
if ($server->getFromDB((int) $input['id'])) {
|
||||
@@ -1148,25 +1178,41 @@ class Server extends CommonDBTM
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="d-flex justify-content-end mb-2">';
|
||||
echo '<input type="text" id="missing-search" class="form-control form-control-sm" placeholder="' . htmlspecialchars(__('Search...', 'urbackup')) . '" style="width:250px">';
|
||||
echo '</div>';
|
||||
|
||||
$formAction = PLUGIN_URBACKUP_WEB_DIR . '/front/server.form.php';
|
||||
|
||||
echo '<table class="table table-striped table-hover">';
|
||||
echo '<table id="missing-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 '<th class="sortable" data-col="0">' . htmlspecialchars(__('Name')) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="1">' . htmlspecialchars(Entity::getTypeName(1)) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="2">' . htmlspecialchars(Location::getTypeName(1)) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="3">' . htmlspecialchars(__('Inventory number')) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="4">' . htmlspecialchars(__('IP address', 'urbackup')) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="5">' . htmlspecialchars(State::getTypeName(1)) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="6">' . htmlspecialchars(User::getTypeName(1)) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th class="sortable" data-col="7">' . htmlspecialchars(Group::getTypeName(1)) . ' <span class="sort-arrow"></span></th>';
|
||||
echo '<th data-col="8">' . htmlspecialchars(__('Actions', 'urbackup')) . '</th>';
|
||||
echo '</tr></thead>';
|
||||
echo '<tbody>';
|
||||
|
||||
foreach ($missingAssets as $asset) {
|
||||
$item = new $asset['itemtype']();
|
||||
$itemLink = '';
|
||||
if ($item instanceof CommonDBTM && $item->getFromDB($asset['items_id'])) {
|
||||
$itemLink = $item->getLinkURL();
|
||||
}
|
||||
|
||||
echo '<tr>';
|
||||
echo '<td>' . htmlspecialchars($asset['name']) . '</td>';
|
||||
echo '<td>';
|
||||
if ($itemLink !== '') {
|
||||
echo '<a href="' . htmlspecialchars($itemLink) . '">' . htmlspecialchars($asset['name']) . '</a>';
|
||||
} else {
|
||||
echo htmlspecialchars($asset['name']);
|
||||
}
|
||||
echo '</td>';
|
||||
echo '<td>' . htmlspecialchars($asset['entity']) . '</td>';
|
||||
echo '<td>' . htmlspecialchars($asset['location']) . '</td>';
|
||||
echo '<td>' . htmlspecialchars($asset['otherserial']) . '</td>';
|
||||
@@ -1190,6 +1236,50 @@ class Server extends CommonDBTM
|
||||
|
||||
echo '</tbody>';
|
||||
echo '</table>';
|
||||
|
||||
echo <<<'JAVASCRIPT'
|
||||
<script>
|
||||
$(function () {
|
||||
var sortDir = {};
|
||||
$('#missing-table th.sortable').on('click', function () {
|
||||
var col = parseInt($(this).data('col'));
|
||||
var $table = $('#missing-table');
|
||||
var $tbody = $table.find('tbody');
|
||||
var rows = $tbody.find('tr').get();
|
||||
|
||||
var dir = sortDir[col] === 'asc' ? 'desc' : 'asc';
|
||||
sortDir[col] = dir;
|
||||
|
||||
rows.sort(function (a, b) {
|
||||
var aVal = $(a).children('td').eq(col).text().trim().toLowerCase();
|
||||
var bVal = $(b).children('td').eq(col).text().trim().toLowerCase();
|
||||
if (aVal < bVal) return dir === 'asc' ? -1 : 1;
|
||||
if (aVal > bVal) return dir === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
$.each(rows, function (i, row) { $tbody.append(row); });
|
||||
|
||||
$table.find('th .sort-arrow').text('');
|
||||
$(this).find('.sort-arrow').text(dir === 'asc' ? '\u25B2' : '\u25BC');
|
||||
});
|
||||
|
||||
$('#missing-search').on('keyup', function () {
|
||||
var val = $(this).val().toLowerCase();
|
||||
$('#missing-table tbody tr').each(function () {
|
||||
var match = false;
|
||||
$(this).children('td').each(function () {
|
||||
if ($(this).text().toLowerCase().indexOf(val) > -1) {
|
||||
match = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
$(this).toggle(match);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
JAVASCRIPT;
|
||||
}
|
||||
|
||||
private static function getCachedName(string $classname, int $id, array &$cache): string
|
||||
@@ -1201,7 +1291,7 @@ class Server extends CommonDBTM
|
||||
$fqcn = '\\' . ltrim($classname, '\\');
|
||||
$obj = new $fqcn();
|
||||
if ($obj->getFromDB($id)) {
|
||||
$cache[$id] = (string) ($obj->fields['name'] ?? '');
|
||||
$cache[$id] = (string) ($obj->fields['completename'] ?? $obj->fields['name'] ?? '');
|
||||
} else {
|
||||
$cache[$id] = '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user