From 7bc18666f67f518d6285e3a0d2d07bbb00e1c1e1 Mon Sep 17 00:00:00 2001 From: Dasc3er Date: Fri, 28 Aug 2020 11:20:20 +0200 Subject: [PATCH] =?UTF-8?q?Base=20per=20controllo=20di=20intergit=C3=A0=20?= =?UTF-8?q?del=20database?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + composer.json | 8 +- gulpfile.js | 15 +++ modules/aggiornamenti/checksum.php | 2 +- modules/aggiornamenti/database.php | 163 +++++++++++++++++++++++++++++ modules/aggiornamenti/edit.php | 14 ++- src/Update.php | 65 ++++++++++++ 7 files changed, 257 insertions(+), 11 deletions(-) create mode 100644 modules/aggiornamenti/database.php diff --git a/.gitignore b/.gitignore index 5103fdefe..4f9e9cea7 100755 --- a/.gitignore +++ b/.gitignore @@ -90,6 +90,7 @@ REVISION .php_cs.cache manifest.json checksum.json +database.json /tests/_log/* /tests/_temp/* diff --git a/composer.json b/composer.json index 41e025384..83c171618 100755 --- a/composer.json +++ b/composer.json @@ -10,13 +10,7 @@ ], "homepage": "https://www.openstamanager.com/", "authors": [{ - "name": "Fabio Lovato", - "email": "info@openstamanager.com" - }, { - "name": "Fabio Piovan", - "email": "info@openstamanager.com" - }, { - "name": "Luca Salvà", + "name": "DevCode s.n.c", "email": "info@openstamanager.com" }], "type": "project", diff --git a/gulpfile.js b/gulpfile.js index c18ce6578..63498181f 100755 --- a/gulpfile.js +++ b/gulpfile.js @@ -370,6 +370,7 @@ function release(done) { glob([ '**/*', '!checksum.json', + '!database.json', '!.idea/**', '!.git/**', '!node_modules/**', @@ -417,6 +418,20 @@ function release(done) { checksumFile.close(); archive.file('checksum.json', {}); + // Aggiunta del file per il controllo di integrità del database + archive.append(shell.exec(`php -r ' + error_reporting(0); + $skip_permissions = true; + include_once __DIR__."/core.php"; + $info = Update::getDatabaseStructure(); + $response = json_encode($info); + echo $response; + '`, { + silent: true + }).stdout, { + name: 'database.json' + }); + // Aggiunta del commit corrente nel file REVISION archive.append(shell.exec('git rev-parse --short HEAD', { silent: true diff --git a/modules/aggiornamenti/checksum.php b/modules/aggiornamenti/checksum.php index bb8d97e45..ac328303d 100644 --- a/modules/aggiornamenti/checksum.php +++ b/modules/aggiornamenti/checksum.php @@ -58,7 +58,7 @@ foreach ($checksum as $file => $md5) { // Schermata di visualizzazione degli errori if (!empty($errors)) { echo ' -

'.tr("Segue l'elenco dei file che presentano checksum diverso rispetto a quello regitrato nella versione ufficiale").'.

+

'.tr("Segue l'elenco dei file che presentano checksum diverso rispetto a quello registrato nella versione ufficiale").'.

'.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_', [ diff --git a/modules/aggiornamenti/database.php b/modules/aggiornamenti/database.php new file mode 100644 index 000000000..cf0dbe1d8 --- /dev/null +++ b/modules/aggiornamenti/database.php @@ -0,0 +1,163 @@ + $value) { + if (array_key_exists($key, $current) && is_array($value)) { + if (!is_array($current[$key])) { + $difference[$key] = $value; + } else { + $new_diff = integrity_diff($value, $current[$key]); + if (!empty($new_diff)) { + $difference[$key] = $new_diff; + } + } + } elseif (!array_key_exists($key, $current) || $current[$key] != $value) { + $difference[$key] = [ + 'current' => $current[$key], + 'expected' => $value, + ]; + } + } + + return !isset($difference) ? [] : $difference; +} + +$file = basename(__FILE__); +$effettua_controllo = filter('effettua_controllo'); + +// Schermata di caricamento delle informazioni +if (empty($effettua_controllo)) { + echo ' +
+ +
+ +
+ '.tr('Caricamento in corso').'... +
+ +'; + + return; +} + +$contents = file_get_contents(DOCROOT.'/database.json'); +$data = json_decode($contents, true); + +if (empty($data)) { + echo ' +
+ '.tr('Impossibile effettuare controlli di integrità in assenza del file _FILE_', [ + '_FILE_' => 'database.json', + ]).'. +
'; + + return; +} + +// Controllo degli errori +$info = Update::getDatabaseStructure(); +$results = integrity_diff($data, $info); + +// Schermata di visualizzazione degli errori +if (!empty($results)) { + echo ' +

'.tr("Segue l'elenco delle tabelle del database che presentano una struttura diversa rispetto a quella prevista nella versione ufficiale del gestionale").'.

+
+ + '.tr('Attenzione: questa funzionalità può presentare dei risultati falsamente positivi, sulla base del contenuto del file _FILE_', [ + '_FILE_' => 'database.json', + ]).'. +
'; + + foreach ($results as $table => $errors) { + echo ' +

'.$table.'

'; + + if (array_key_exists('current', $errors) && $errors['current'] == null) { + echo ' +

'.tr('Tabella assente').'

'; + continue; + } + + $foreign_keys = $errors['foreign_keys'] ?: []; + unset($errors['foreign_keys']); + + if (!empty($errors)) { + echo ' + + + + + + + + + '; + + foreach ($errors as $name => $diff) { + echo ' + + + + '; + } + + echo ' + +
'.tr('Colonna').''.tr('Conflitto').'
+ '.$name.' + + '.json_encode($diff).' +
'; + } + + if (!empty($foreign_keys)) { + echo ' + + + + + + + + + '; + + foreach ($foreign_keys as $name => $diff) { + echo ' + + + + '; + } + + echo ' + +
'.tr('Foreign keys').''.tr('Conflitto').'
+ '.$name.' + + '.json_encode($diff).' +
'; + } + } +} else { + echo ' +
+ '.tr('Il database non presenta problemi di integrità').'. +
'; +} diff --git a/modules/aggiornamenti/edit.php b/modules/aggiornamenti/edit.php index fd7a38ab7..329123dc5 100755 --- a/modules/aggiornamenti/edit.php +++ b/modules/aggiornamenti/edit.php @@ -117,7 +117,11 @@ function update() { } function checksum(button) { - openModal("'.tr('Controllo di integrità').'", "'.$module->fileurl('checksum.php').'?id_module='.$id_module.'"); + openModal("'.tr('Controllo dei file').'", "'.$module->fileurl('checksum.php').'?id_module='.$id_module.'"); +} + +function database(button) { + openModal("'.tr('Controllo del database').'", "'.$module->fileurl('database.php').'?id_module='.$id_module.'"); } function search(button) { @@ -170,12 +174,16 @@ function search(button) {

- '.tr("Verifica l'integrità dell'intallazione").' + '.tr("Verifica l'integrità dell'intallazione").'

+ +
diff --git a/src/Update.php b/src/Update.php index 4d833fac8..fbe41d860 100755 --- a/src/Update.php +++ b/src/Update.php @@ -302,6 +302,71 @@ class Update return false; } + + return true; + } + + /** + * Restituisce un riepilogo sulla struttura delle tabelle del gestionale. + * + * @throws Exception + * + * @return array + */ + public static function getDatabaseStructure() + { + // Tabelle registrate per il gestionale + $tables = include DOCROOT.'/update/tables.php'; + + $database = database(); + $database_name = $database->getDatabaseName(); + + $info = []; + foreach ($tables as $table) { + if ($database->tableExists($table)) { + // Individuazione delle colonne per la tabella + $query = 'SHOW COLUMNS FROM `'.$table.'` IN `'.$database_name.'`'; + $columns_found = $database->fetchArray($query); + + // Organizzazione delle colonne per nome + $columns = []; + foreach ($columns_found as $column) { + $column = array_change_key_case($column); + $name = $column['field']; + unset($column['field']); + + $columns[$name] = $column; + } + + // Individuazione delle chiavi esterne della tabella + $fk_query = 'SELECT + CONSTRAINT_NAME AS `name`, + COLUMN_NAME AS `column`, + REFERENCED_TABLE_NAME AS `referenced_table`, + REFERENCED_COLUMN_NAME AS `referenced_column` + FROM information_schema.KEY_COLUMN_USAGE + WHERE TABLE_NAME = '.prepare($table).' + AND TABLE_SCHEMA = '.prepare($database_name).' + AND REFERENCED_TABLE_SCHEMA = '.prepare($database_name); + $fks_found = $database->fetchArray($fk_query); + + // Organizzazione delle chiavi esterne per nome + $fks = []; + foreach ($fks_found as $fk) { + $fk = array_change_key_case($fk); + $name = $fk['name']; + unset($fk['name']); + + $fks[$name] = $fk; + } + + $info[$table] = array_merge($columns, [ + 'foreign_keys' => $fks, + ]); + } + } + + return $info; } /**