Skip to content

Commit 60f4bf7

Browse files
committed
feat(install): check schema prior to upgrade
1 parent 814729b commit 60f4bf7

File tree

3 files changed

+87
-11
lines changed

3 files changed

+87
-11
lines changed

install/install.php

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@
3636
use Glpi\Dashboard\Dashboard;
3737
use Glpi\Dashboard\Item as Dashboard_Item;
3838
use Glpi\Dashboard\Right as Dashboard_Right;
39-
39+
use Glpi\System\Diagnostic\DatabaseSchemaIntegrityChecker;
4040
use Ramsey\Uuid\Uuid;
41+
4142
class PluginFormcreatorInstall {
4243
protected $migration;
4344

@@ -125,15 +126,24 @@ public function upgrade(Migration $migration, $args = []): bool {
125126
}
126127
if ($hasMyisamTables) {
127128
// Need to convert myisam tables into innodb first
129+
$message = __('Upgrade tables to innoDB; run php bin/console glpi:migration:myisam_to_innodb', 'formcreator');
128130
if (isCommandLine()) {
129-
echo "Upgrade tables to innoDB; run php bin/console glpi:migration:myisam_to_innodb" . PHP_EOL;
131+
echo $message . PHP_EOL;
130132
} else {
131-
Session::addMessageAfterRedirect(__('Upgrade tables to innoDB; run php bin/console glpi:migration:myisam_to_innodb', 'formcreator'), false, ERROR);
133+
Session::addMessageAfterRedirect($message, false, ERROR);
132134
}
133135
return false;
134136
}
135137
}
136138

139+
// Check schema of tables
140+
if (!isset($args['skip-db-check'])) {
141+
$oldVersion = Config::getConfigurationValue('formcreator', 'previous_version');
142+
if ($oldVersion !== null && !$this->checkSchema($oldVersion)) {
143+
return false;
144+
}
145+
}
146+
137147
$this->migration = $migration;
138148
if (isset($args['force-upgrade']) && $args['force-upgrade'] === true) {
139149
// Might return false
@@ -262,7 +272,7 @@ public function isPluginInstalled() {
262272
protected function installSchema() {
263273
global $DB;
264274

265-
$dbFile = __DIR__ . '/mysql/plugin_formcreator_empty.sql';
275+
$dbFile = plugin_formcreator_getSchemaPath();
266276
if (!$DB->runFile($dbFile)) {
267277
$this->migration->displayWarning("Error creating tables : " . $DB->error(), true);
268278
die('Giving up');
@@ -733,4 +743,68 @@ public function deleteMiniDashboard(): bool {
733743

734744
return true;
735745
}
746+
747+
/**
748+
* Check the schema of all tables of the plugin against the expected schema of the given version
749+
*
750+
* @return boolean
751+
*/
752+
public function checkSchema(string $version): bool {
753+
global $DB;
754+
755+
$schemaFile = plugin_formcreator_getSchemaPath($version);
756+
757+
$checker = new DatabaseSchemaIntegrityChecker(
758+
$DB,
759+
true,
760+
false,
761+
false,
762+
false,
763+
false,
764+
false
765+
);
766+
767+
try {
768+
$differences = $checker->checkCompleteSchema($schemaFile, true, 'plugin:formcreator');
769+
} catch (\Throwable $e) {
770+
$message = __('Failed to check the sanity of the tables!', 'formcreator');
771+
if (isCommandLine()) {
772+
echo $message . PHP_EOL;
773+
} else {
774+
Session::addMessageAfterRedirect($message, false, ERROR);
775+
}
776+
return false;
777+
}
778+
779+
if (count($differences) > 0) {
780+
if (!isCommandLine()) {
781+
Session::addMessageAfterRedirect(sprintf(
782+
__('Inconsistencies detected in the database. To see the logs run the command %s', 'formcreator'),
783+
'bin/console glpi:plugin:install formcreator'
784+
), false, ERROR);
785+
}
786+
foreach ($differences as $table_name => $difference) {
787+
$message = null;
788+
switch ($difference['type']) {
789+
case DatabaseSchemaIntegrityChecker::RESULT_TYPE_ALTERED_TABLE:
790+
$message = sprintf(__('Table schema differs for table "%s".'), $table_name);
791+
break;
792+
case DatabaseSchemaIntegrityChecker::RESULT_TYPE_MISSING_TABLE:
793+
$message = sprintf(__('Table "%s" is missing.'), $table_name);
794+
break;
795+
case DatabaseSchemaIntegrityChecker::RESULT_TYPE_UNKNOWN_TABLE:
796+
$message = sprintf(__('Unknown table "%s" has been found in database.'), $table_name);
797+
break;
798+
}
799+
if (isCommandLine()) {
800+
echo $message . PHP_EOL;
801+
echo $difference['diff'] . PHP_EOL;
802+
}
803+
}
804+
805+
return false;
806+
}
807+
808+
return true;
809+
}
736810
}

setup.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ function plugin_version_formcreator() {
6565
}
6666

6767
$glpiVersion = rtrim(GLPI_VERSION, '-dev');
68-
if (!method_exists('Plugins', 'checkGlpiVersion') && version_compare($glpiVersion, PLUGIN_FORMCREATOR_GLPI_MIN_VERSION, 'lt')) {
68+
if (!method_exists($plugin, 'checkGlpiVersion') && version_compare($glpiVersion, PLUGIN_FORMCREATOR_GLPI_MIN_VERSION, 'lt')) {
6969
echo 'This plugin requires GLPI >= ' . PLUGIN_FORMCREATOR_GLPI_MIN_VERSION;
7070
return false;
7171
}
@@ -502,6 +502,11 @@ function plugin_formcreator_options() {
502502
*
503503
* @return string|null
504504
*/
505-
function plugin_formcreator_getSchemaPath(): ?string {
506-
return Plugin::getPhpDir('formcreator') . '/install/mysql/plugin_formcreator_empty.sql';
505+
function plugin_formcreator_getSchemaPath(string $version = null): ?string {
506+
if ($version === null) {
507+
$matches = [];
508+
preg_match('/^(\d+\.\d+\.\d+)/', PLUGIN_FORMCREATOR_VERSION, $matches);
509+
$version = $matches[1];
510+
}
511+
return Plugin::getPhpDir('formcreator') . "/install/mysql/plugin_formcreator_${version}_empty.sql";
507512
}

tests/1-install/Config.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,7 @@ public function checkConfig() {
169169
$pluginName = TEST_PLUGIN_NAME;
170170

171171
// Check the version saved in configuration
172-
$config = \Config::getConfigurationValues($pluginName);
173-
$this->array($config)->isIdenticalTo([
174-
'schema_version' => PLUGIN_FORMCREATOR_SCHEMA_VERSION
175-
]);
172+
$this->string(\Config::getConfigurationValue($pluginName, 'schema_version'))->isEqualTo(PLUGIN_FORMCREATOR_SCHEMA_VERSION);
176173
}
177174

178175
public function checkRequestType() {

0 commit comments

Comments
 (0)