Files
urbackup/install/install.php
T
2026-08-07 14:27:33 +02:00

447 lines
11 KiB
PHP

<?php
declare(strict_types=1);
/**
* -------------------------------------------------------------------------
* UrBackup plugin for GLPI
* -------------------------------------------------------------------------
*/
use GlpiPlugin\Urbackup\Config;
use GlpiPlugin\Urbackup\Profile;
use GlpiPlugin\Urbackup\Server;
if (!defined('GLPI_ROOT')) {
die(__('Sorry. You cannot access this file directly.', 'urbackup'));
}
/**
* Install or update plugin database schema and default data.
*
* @return bool
*/
function plugin_urbackup_install_process(): bool
{
$migration = new Migration(PLUGIN_URBACKUP_VERSION);
$migration->displayMessage(__('UrBackup plugin installation', 'urbackup'));
plugin_urbackup_install_create_initial_schema($migration);
plugin_urbackup_install_update_configs_table($migration);
// Convert old assettype configurations to GLPI 11 capacity system
plugin_urbackup_install_convert_assettypes_to_capacities($migration);
plugin_urbackup_install_update_servers_table($migration);
plugin_urbackup_install_update_serverassets_table($migration);
plugin_urbackup_install_encrypt_api_passwords();
plugin_urbackup_install_add_enable_computer_config();
// Drop tables that are no longer used (replaced by Profile::registerRights() and Capacity system)
plugin_urbackup_install_drop_legacy_tables($migration);
$migration->executeMigration();
Profile::installRights();
return true;
}
/**
* Create initial database schema from SQL file.
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_create_initial_schema(Migration $migration): void
{
global $DB;
$required_tables = [
'glpi_plugin_urbackup_configs',
'glpi_plugin_urbackup_servers',
'glpi_plugin_urbackup_serverassets',
];
$missing_table_found = false;
foreach ($required_tables as $table) {
if (!$DB->tableExists($table)) {
$missing_table_found = true;
break;
}
}
if (!$missing_table_found) {
return;
}
$migration->displayMessage(__('Creating UrBackup plugin database schema', 'urbackup'));
$db_file = PLUGIN_URBACKUP_DIR . '/install/mysql/plugin_urbackup-empty.sql';
if (!file_exists($db_file)) {
$migration->displayMessage(
sprintf(
__('Database schema file not found: %s', 'urbackup'),
$db_file
)
);
return;
}
if (!$DB->runFile($db_file)) {
$migration->displayMessage(__('Error while creating UrBackup plugin database schema', 'urbackup'));
}
}
/**
* Update configs table.
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_update_configs_table(Migration $migration): void
{
global $DB;
$table = 'glpi_plugin_urbackup_configs';
if (!$DB->tableExists($table)) {
return;
}
$migration->addField($table, 'name', 'string', [
'value' => '',
'after' => 'id',
]);
$migration->addField($table, 'value', 'text', [
'after' => 'name',
]);
$migration->addField($table, 'date_creation', 'timestamp');
$migration->addField($table, 'date_mod', 'timestamp');
$migration->addKey($table, 'name');
}
/**
* Update servers table.
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_update_servers_table(Migration $migration): void
{
global $DB;
$table = 'glpi_plugin_urbackup_servers';
if (!$DB->tableExists($table)) {
return;
}
$migration->addField($table, 'entities_id', 'integer', [
'value' => 0,
'after' => 'id',
]);
$migration->addField($table, 'is_recursive', 'bool', [
'value' => 0,
'after' => 'entities_id',
]);
$migration->addField($table, 'name', 'string', [
'value' => '',
'after' => 'is_recursive',
]);
$migration->addField($table, 'locations_id', 'integer', [
'value' => 0,
'after' => 'name',
]);
$migration->addField($table, 'users_id', 'integer', [
'value' => 0,
'after' => 'locations_id',
]);
$migration->addField($table, 'ip_address', 'string', [
'value' => '',
'after' => 'locations_id',
]);
$migration->addField($table, 'port', 'integer', [
'value' => 55414,
'after' => 'ip_address',
]);
$migration->addField($table, 'protocol', 'string', [
'value' => 'http',
'after' => 'port',
]);
$migration->addField($table, 'server_version', 'string', [
'after' => 'protocol',
]);
$migration->addField($table, 'api_username', 'string', [
'after' => 'server_version',
]);
$migration->addField($table, 'api_password', 'text', [
'after' => 'api_username',
]);
$migration->addField($table, 'ignore_ssl', 'bool', [
'value' => 0,
'after' => 'api_password',
]);
$migration->addField($table, 'is_active', 'bool', [
'value' => 1,
'after' => 'ignore_ssl',
]);
$migration->addField($table, 'last_api_status', 'bool', [
'value' => 0,
'after' => 'is_active',
]);
$migration->addField($table, 'last_api_message', 'text', [
'after' => 'last_api_status',
]);
$migration->addField($table, 'last_api_check', 'timestamp', [
'after' => 'last_api_message',
]);
$migration->addField($table, 'comment', 'text', [
'after' => 'last_api_check',
]);
$migration->addField($table, 'host_itemtype', 'string', [
'after' => 'comment',
]);
$migration->addField($table, 'host_items_id', 'integer', [
'value' => 0,
'after' => 'host_itemtype',
]);
$migration->addField($table, 'date_creation', 'timestamp');
$migration->addField($table, 'date_mod', 'timestamp');
$migration->addKey($table, 'name');
$migration->addKey($table, 'entities_id');
$migration->addKey($table, 'locations_id');
$migration->addKey($table, 'users_id');
$migration->addKey($table, 'is_active');
$migration->addKey($table, ['locations_id', 'is_active'], 'location_active');
$migration->addKey($table, ['host_itemtype', 'host_items_id'], 'host_asset');
}
/**
* Update serverassets table.
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_update_serverassets_table(Migration $migration): void
{
global $DB;
$table = 'glpi_plugin_urbackup_serverassets';
if (!$DB->tableExists($table)) {
return;
}
$migration->addField($table, 'plugin_urbackup_servers_id', 'integer', [
'value' => 0,
'after' => 'id',
]);
$migration->addField($table, 'itemtype', 'string', [
'value' => '',
'after' => 'plugin_urbackup_servers_id',
]);
$migration->addField($table, 'items_id', 'integer', [
'value' => 0,
'after' => 'itemtype',
]);
$migration->addField($table, 'date_creation', 'timestamp');
$migration->addField($table, 'date_mod', 'timestamp');
$migration->addKey($table, 'plugin_urbackup_servers_id');
$migration->addKey($table, ['itemtype', 'items_id'], 'item');
}
/**
* Encrypt api_password values still stored in plaintext.
*
* Runs on every install/update, but skips values that already use the
* GLPIKey encrypted format (idempotent). If the GLPI key is unavailable,
* the plaintext value is kept to avoid data loss.
*
* @return void
*/
function plugin_urbackup_install_encrypt_api_passwords(): void
{
global $DB;
$table = 'glpi_plugin_urbackup_servers';
if (!$DB->tableExists($table)) {
return;
}
$iterator = $DB->request([
'FROM' => $table,
'WHERE' => ['api_password' => ['<>', '']],
]);
foreach ($iterator as $row) {
$password = (string) $row['api_password'];
if ($password === '' || Server::isApiPasswordEncrypted($password)) {
continue;
}
$encrypted = (new GLPIKey())->encrypt($password);
if ($encrypted === '') {
continue;
}
$DB->update(
$table,
['api_password' => $encrypted],
['id' => (int) $row['id']]
);
}
}
/**
* Ensure the `enable_computer` config row exists (default: enabled).
*
* Computer is registered as a plain tab (not a capacity), so its default
* state must be stored in the config table to keep it backward compatible
* with previous versions where Computer was always enabled. Idempotent.
*
* @return void
*/
function plugin_urbackup_install_add_enable_computer_config(): void
{
global $DB;
$table = 'glpi_plugin_urbackup_configs';
if (!$DB->tableExists($table)) {
return;
}
$iterator = $DB->request([
'FROM' => $table,
'WHERE' => ['name' => 'enable_computer'],
]);
if (count($iterator) > 0) {
return;
}
$DB->insert($table, [
'name' => 'enable_computer',
'value' => '1',
'date_creation' => $_SESSION['glpi_currenttime'] ?? date('Y-m-d H:i:s'),
]);
}
/**
* Drop a plugin table through Migration.
*
* Shared helper used by both install and uninstall processes
* (uninstall.php requires install.php to get this function).
*
* @param Migration $migration Migration instance
* @param string $table Table name
*
* @return void
*/
function plugin_urbackup_migration_drop_table(Migration $migration, string $table): void
{
global $DB;
if (!$DB->tableExists($table)) {
return;
}
$migration->dropTable($table);
}
/**
* Drop legacy tables that are no longer used.
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_drop_legacy_tables(Migration $migration): void
{
global $DB;
// glpi_plugin_urbackup_profiles was replaced by Profile::registerRights() in 0.5.0
plugin_urbackup_migration_drop_table($migration, 'glpi_plugin_urbackup_profiles');
// glpi_plugin_urbackup_assettypes was replaced by GLPI 11 Capacity system in 0.6.0
plugin_urbackup_migration_drop_table($migration, 'glpi_plugin_urbackup_assettypes');
}
/**
* Convert old glpi_plugin_urbackup_assettypes to GLPI 11 capacity system.
*
* The legacy table is only kept to drop the obsolete `is_default` column.
* Enabling/disabling the UrBackup capacity on Asset Definitions is done by
* the admin via the native Capacities UI (Config > Asset definitions >
* Capacities). GLPI 11.0.x provides no public API to programmatically enable
* a capacity (it is processed from the `capacities` form input in
* AssetDefinition::post_updateItem()).
*
* @param Migration $migration Migration instance
*
* @return void
*/
function plugin_urbackup_install_convert_assettypes_to_capacities(Migration $migration): void
{
global $DB;
$table = Config::getAssetTypesTable();
if (!$DB->tableExists($table)) {
return;
}
// Check if is_default column exists
$has_is_default = false;
foreach ($DB->listFields($table) as $col) {
if ($col['Field'] === 'is_default') {
$has_is_default = true;
break;
}
}
// Drop is_default column (no longer needed in capacity system)
if ($has_is_default) {
$migration->dropField($table, 'is_default');
}
}