From 6eb7213cf7b84caf1995301f806fef9d20f4627d Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Fri, 22 Mar 2013 21:34:01 +0100 Subject: [PATCH] Adding some fixes when executing chamilo:install 1.8.8.4 and then executing chamilo:upgrade 1.10 course tables are not yet migrated. See BT#5572 --- main/inc/global.inc.php | 52 +++-- main/install/configuration.dist.yml.php | 2 +- main/install/install.lib.php | 3 +- .../Command/Database/InstallCommand.php | 207 ++++++++++++++---- .../Command/Database/UpgradeCommand.php | 12 +- src/ChamiloLMS/Migrations/Version10.php | 6 +- src/ChamiloLMS/Migrations/Version11.php | 23 ++ src/ChamiloLMS/Migrations/Version8.php | 2 +- src/ChamiloLMS/Migrations/Version9.php | 6 +- tests/doctrine_console/cli-config.php | 33 ++- 10 files changed, 258 insertions(+), 88 deletions(-) create mode 100755 src/ChamiloLMS/Migrations/Version11.php diff --git a/main/inc/global.inc.php b/main/inc/global.inc.php index d5dcd5bc93..194b10dfa6 100755 --- a/main/inc/global.inc.php +++ b/main/inc/global.inc.php @@ -16,7 +16,6 @@ * This script returns a $app Application instance so you have access to all the services. * * @package chamilo.include - * @todo isn't configuration.php renamed to configuration.inc.php yet? * @todo use the $_configuration array for all the needed variables * */ @@ -38,6 +37,7 @@ $includePath = dirname(__FILE__); // @todo Isn't this file renamed to configuration.inc.php yet? // Include the main Chamilo platform configuration file. $main_configuration_file_path = $includePath.'/conf/configuration.php'; +$configurationYML = $includePath.'/conf/configuration.yml'; $already_installed = false; if (file_exists($main_configuration_file_path)) { @@ -47,6 +47,10 @@ if (file_exists($main_configuration_file_path)) { $_configuration = array(); } +if (file_exists($configurationYML)) { + $already_installed = true; +} + //Redirects to the main/install/ page /* if (!$already_installed) { @@ -56,23 +60,6 @@ if (!$already_installed) { die(); }*/ -// Ensure that _configuration is in the global scope before loading -// main_api.lib.php. This is particularly helpful for unit tests -if (!isset($GLOBALS['_configuration'])) { - $GLOBALS['_configuration'] = $_configuration; -} - -// Code for trnasitional purposes, it can be removed right before the 1.8.7 release. -if (empty($_configuration['system_version'])) { - $_configuration['system_version'] = (!empty($_configuration['dokeos_version']) ? $_configuration['dokeos_version'] : ''); - $_configuration['system_stable'] = (!empty($_configuration['dokeos_stable']) ? $_configuration['dokeos_stable'] : ''); - $_configuration['software_url'] = 'http://www.chamilo.org/'; -} - -// For backward compatibility. -$_configuration['dokeos_version'] = $_configuration['system_version']; -$_configuration['dokeos_stable'] = $_configuration['system_stable']; -$userPasswordCrypted = (!empty($_configuration['password_encryption']) ? $_configuration['password_encryption'] : 'sha1'); // Include the main Chamilo platform library file. require_once $includePath.'/lib/main_api.lib.php'; @@ -121,15 +108,31 @@ use Symfony\Component\Yaml\Parser; $app = new Application(); //Overwriting $_configuration - -$configurationYML = $includePath.'/conf/configuration.yml'; - if (file_exists($configurationYML)) { $yaml = new Parser(); $_configuration = $yaml->parse(file_get_contents($configurationYML)); } +// Ensure that _configuration is in the global scope before loading +// main_api.lib.php. This is particularly helpful for unit tests +if (!isset($GLOBALS['_configuration'])) { + $GLOBALS['_configuration'] = $_configuration; +} + +// Code for trnasitional purposes, it can be removed right before the 1.8.7 release. +if (empty($_configuration['system_version'])) { + $_configuration['system_version'] = (!empty($_configuration['dokeos_version']) ? $_configuration['dokeos_version'] : ''); + $_configuration['system_stable'] = (!empty($_configuration['dokeos_stable']) ? $_configuration['dokeos_stable'] : ''); + $_configuration['software_url'] = 'http://www.chamilo.org/'; +} + +// For backward compatibility. +$_configuration['dokeos_version'] = $_configuration['system_version']; +$_configuration['dokeos_stable'] = $_configuration['system_stable']; +$userPasswordCrypted = (!empty($_configuration['password_encryption']) ? $_configuration['password_encryption'] : 'sha1'); + $app['configuration_file'] = $main_configuration_file_path; +$app['configuration_yml_file'] = $configurationYML; $app['configuration'] = $_configuration; $app['languages_file'] = array(); $app['installed'] = $already_installed; @@ -416,8 +419,6 @@ class ChamiloServiceProvider implements ServiceProviderInterface { public function register(Application $app) { - - //Template $app['template'] = $app->share(function () use ($app) { $template = new Template(null, $app); @@ -534,7 +535,6 @@ if (!empty($_configuration['multiple_access_urls'])) { } $charset = 'UTF-8'; - $checkConnection = false; if (isset($_configuration['main_database'])) { @@ -870,7 +870,7 @@ if (api_get_setting('server_type') == 'test') { $app->before( function () use ($app, $checkConnection) { - if (!file_exists($app['configuration_file'])) { + if (!file_exists($app['configuration_file']) && !file_exists($app['configuration_yml_file'])) { return new RedirectResponse(api_get_path(WEB_CODE_PATH).'install'); $app->abort(500, "Incorrect PHP version"); } @@ -968,8 +968,6 @@ if (empty($default_quota)) { define('DEFAULT_DOCUMENT_QUOTA', $default_quota); - - $app['pages.controller'] = $app->share(function () use ($app) { return new PagesController($app['pages.repository']); }); diff --git a/main/install/configuration.dist.yml.php b/main/install/configuration.dist.yml.php index 3b01c3ff4b..fc2378afef 100644 --- a/main/install/configuration.dist.yml.php +++ b/main/install/configuration.dist.yml.php @@ -33,7 +33,7 @@ $_configuration['db_host'] = 'localhost'; // Your MySQL username $_configuration['db_user'] = 'root'; // Your MySQL password -$_configuration['db_password'] = 'root'; +$_configuration['db_password'] = 'dokeosla'; /** * Database settings diff --git a/main/install/install.lib.php b/main/install/install.lib.php index a9b2615251..c80a30a86a 100755 --- a/main/install/install.lib.php +++ b/main/install/install.lib.php @@ -35,7 +35,8 @@ function is_already_installed_system() } $current_config_file = api_get_path(CONFIGURATION_PATH).'configuration.php'; - if (!file_exists($current_config_file)) { + + if (!file_exists($current_config_file) && !file_exists(api_get_path(CONFIGURATION_PATH).'configuration.yml')) { return false; // Configuration file does not exist, install the system. } require $current_config_file; diff --git a/src/ChamiloLMS/Command/Database/InstallCommand.php b/src/ChamiloLMS/Command/Database/InstallCommand.php index 4d3b7725f1..c52b92175e 100644 --- a/src/ChamiloLMS/Command/Database/InstallCommand.php +++ b/src/ChamiloLMS/Command/Database/InstallCommand.php @@ -31,7 +31,7 @@ class InstallCommand extends AbstractCommand * * @return string */ - public function getConfigurationFile() + public function getConfigurationPath() { return api_get_path(SYS_PATH).'main/inc/conf/'; } @@ -48,6 +48,13 @@ class InstallCommand extends AbstractCommand return api_get_path(SYS_PATH).'main/install/'.$version.'/'; } + public function getAvailableVersions() { + return array( + '1.8.8.4', + '1.9.0', + '1.10' + ); + } /** * Executes a command via CLI @@ -59,18 +66,19 @@ class InstallCommand extends AbstractCommand */ protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output) { - $configurationPath = $this->getConfigurationFile(); + $configurationPath = $this->getConfigurationPath(); $dialog = $this->getHelperSet()->get('dialog'); $version = $input->getArgument('version'); + $defaultVersion = $this->getLatestVersion(); if (empty($version)) { $version = $defaultVersion; } - $output->writeln("Welcome to the Chamilo installation process!"); + $output->writeln("Welcome to the Chamilo installation process."); if (!is_writable($configurationPath)) { $output->writeln("Folder ".$configurationPath." must be writable"); @@ -79,31 +87,32 @@ class InstallCommand extends AbstractCommand $sqlFolder = $this->getInstallationPath($version); if (!is_dir($sqlFolder)) { - $output->writeln("Sorry you can't install Chamilo :( Installation files for version $version does not exists: ".$sqlFolder); + $output->writeln("Sorry you can't install that version of Chamilo :( Supported versions: ".implode(', ', $this->getAvailableVersions())); return false; } - /*if (!$dialog->askConfirmation( - $output, - 'You are about to install Chamilo $version here:'.$configurationPath.' Are you sure?(y/N)', - false - ) - ) { - return; - }*/ - /* - if (file_exists($configurationPath.'configuration.php') || file_exists($configurationPath.'configuration.yml')) { - if (!$dialog->askConfirmation( - $output, - 'There is a Chamilo installation located here: '.$configurationPath.' Are you sure you want to continue?(y/N)', - false - ) - ) { - return; - } - }*/ + if (file_exists($configurationPath.'configuration.php') || file_exists($configurationPath.'configuration.yml')) { + if (!$dialog->askConfirmation( + $output, + 'There is a Chamilo installation located here: '.$configurationPath.' Are you sure you want to continue?(y/N)', + false + ) + ) { + return; + } + + if (!$dialog->askConfirmation( + $output, + 'This will be a fresh installation. Old databases and config files will be deleted. Are you sure?(y/N)', + false + ) + ) { + return; + } + $this->cleanInstallation($output); + } //Getting default configuration parameters require_once api_get_path(SYS_PATH).'main/install/configuration.dist.yml.php'; @@ -142,16 +151,37 @@ class InstallCommand extends AbstractCommand } } - //Installing database - $result = $this->install($version, $newConfigurationArray, $output); + $configurationWasSaved = $this->writeConfiguration($newConfigurationArray, $version); - if ($result) { - $this->createAdminUser($newConfigurationArray, $output); - $this->writeConfiguration($newConfigurationArray, $version); - $output->writeln("Database installation finished!"); + if ($configurationWasSaved) { + + //Installing database + $result = $this->install($version, $newConfigurationArray, $output); + + if ($result) { + $this->createAdminUser($newConfigurationArray, $output); + + $output->writeln("Chamilo was successfully installed. Go to your browser and enter: ".$newConfigurationArray['root_web']); + } } } + /** + * Deletes configuration files + */ + function cleanInstallation($output) + { + $confPath = $this->getConfigurationPath(); + if (file_exists($confPath.'configuration.yml')) { + unlink($confPath.'configuration.yml'); + } + + if (file_exists($confPath.'configuration.php')) { + unlink($confPath.'configuration.php'); + } + $output->writeln("Config files were deleted."); + } + /** * * @param $newConfigurationArray @@ -163,8 +193,6 @@ class InstallCommand extends AbstractCommand $dialog = $this->getHelperSet()->get('dialog'); //Creating admin user - $output->writeln("Chamilo was successfully installed visit: ".$newConfigurationArray['root_web']); - $adminUser = array( 'lastname' => 'Julio', 'firstname' => 'M', @@ -172,7 +200,6 @@ class InstallCommand extends AbstractCommand 'password' => 'admin', 'email' => 'admin@example.org' ); - $output->writeln("Creating an admin User"); $userInfo = array(); foreach ($adminUser as $key => $value) { @@ -183,9 +210,13 @@ class InstallCommand extends AbstractCommand ); $userInfo[$key] = $data; } - $userInfo = \UserManager::add($userInfo); - if ($userInfo && isset($userInfo['user_id'])) { - $userId = $userInfo['user_id']; + //By default admin is = 1 so we update it + $userId = $userInfo['user_id'] = 1; + $userInfo['auth_source'] = 'platform'; + $userInfo['password'] = api_get_encrypted_password($userInfo['password']); + + $result = \UserManager::update($userInfo); + if ($result) { \UserManager::add_user_as_admin($userInfo['user_id']); $output->writeln("User admin created with id: $userId"); @@ -210,13 +241,55 @@ class InstallCommand extends AbstractCommand */ public function writeConfiguration($newConfigurationArray, $version) { - $configurationPath = $this->getConfigurationFile(); + $configurationPath = $this->getConfigurationPath(); $newConfigurationArray['system_version'] = $version; $dumper = new Dumper(); $yaml = $dumper->dump($newConfigurationArray, 2); //inline $newConfigurationFile = $configurationPath.'configuration.yml'; file_put_contents($newConfigurationFile, $yaml); + return file_exists($newConfigurationFile); + } + + private function setDatabaseSettings($_configuration) + { + global $config; + + $defaultConnection = array( + 'driver' => 'pdo_mysql', + 'dbname' => $_configuration['main_database'], + 'user' => $_configuration['db_user'], + 'password' => $_configuration['db_password'], + 'host' => $_configuration['db_host'], + ); + + $em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config); + + //Fixes some errors + $platform = $em->getConnection()->getDatabasePlatform(); + $platform->registerDoctrineTypeMapping('enum', 'string'); + $platform->registerDoctrineTypeMapping('set', 'string'); + + $helpers = array( + 'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()), + 'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em), + ); + + foreach ($helpers as $name => $helper) { + $this->getApplication()->getHelperSet()->set($helper, $name); + } + + $conn_return = @\Database::connect( + array( + 'server' => $_configuration['db_host'], + 'username' => $_configuration['db_user'], + 'password' => $_configuration['db_password'], + // 'persistent' => $_configuration['db_persistent_connection'] + // When $_configuration['db_persistent_connection'] is set, it is expected to be a boolean type. + )); + + global $database_connection; + $checkConnection = @\Database::select_db($_configuration['main_database'], $database_connection); } /** @@ -230,9 +303,23 @@ class InstallCommand extends AbstractCommand public function install($version, $_configuration, $output) { $sqlFolder = $this->getInstallationPath($version); + + $this->setDatabaseSettings($_configuration); + $output->writeln("Creating database ... "); - $result = $this->createDatabase($_configuration); + $testConnection = $this->testDatabaseConnection($_configuration['db_host'], $_configuration['db_user'], $_configuration['db_password']); + + if ($testConnection == 1) { + $output->writeln("Connection stablished with the DB"); + } else { + $output->writeln("No access to the database for user:".$_configuration['db_user'].""); + exit; + } + + $result = $this->dropAndCreateDatabase($_configuration); + + //Importing files if ($result) { @@ -250,12 +337,21 @@ class InstallCommand extends AbstractCommand $input = new ArrayInput($arguments); $command->run($input, $output); - //Getting extra information about the installation - $result = \Database::query("SELECT selected_value FROM ".\Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT)." WHERE variable = 'chamilo_database_version'"); - $result = \Database::fetch_array($result); - - $output->writeln("Showing chamilo_database_version value: ".$result['selected_value']); + api_set_setting('Institution', 'Portal'); + api_set_setting('InstitutionUrl', 'Portal'); + api_set_setting('siteName', 'Campus'); + api_set_setting('emailAdministrator', 'admin@example.org'); + api_set_setting('administratorSurname', 'M'); + api_set_setting('administratorName', 'Julio'); + api_set_setting('platformLanguage', 'english'); + api_set_setting('allow_registration', '1'); + api_set_setting('allow_registration_as_teacher', '1'); + //Getting extra information about the installation + //$value = api_get_setting('chamilo_database_version'); + //$output->writeln("Showing chamilo_database_version value: ".$value); + $output->writeln("Check your installation status with chamilo:status"); + $output->writeln("Database process ended!"); return true; } } @@ -266,7 +362,7 @@ class InstallCommand extends AbstractCommand * * @return resource */ - public function createDatabase($_configuration) + public function dropAndCreateDatabase($_configuration) { /* $command = $this->getApplication()->find('orm:schema-tool:create'); @@ -277,6 +373,31 @@ class InstallCommand extends AbstractCommand $command->run($input, $output); exit; */ + \Database::query("DROP DATABASE ".mysql_real_escape_string($_configuration['main_database']).""); return \Database::query("CREATE DATABASE IF NOT EXISTS ".mysql_real_escape_string($_configuration['main_database'])." DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci"); } + + /** + * In step 3. Tests establishing connection to the database server. + * If it's a single database environment the function checks if the database exist. + * If the database doesn't exist we check the creation permissions. + * + * @return int 1 when there is no problem; + * 0 when a new database is impossible to be created, then the single/multiple database configuration is impossible too + * -1 when there is no connection established. + */ + public function testDatabaseConnection($dbHostForm, $dbUsernameForm, $dbPassForm) + { + $dbConnect = -1; + //Checking user credentials + if (@\Database::connect( + array('server' => $dbHostForm, 'username' => $dbUsernameForm, 'password' => $dbPassForm) + ) !== false + ) { + $dbConnect = 1; + } else { + $dbConnect = -1; + } + return $dbConnect; //return 1, if no problems, "0" if, in case we can't create a new DB and "-1" if there is no connection. + } } \ No newline at end of file diff --git a/src/ChamiloLMS/Command/Database/UpgradeCommand.php b/src/ChamiloLMS/Command/Database/UpgradeCommand.php index e87242e354..85178e0147 100644 --- a/src/ChamiloLMS/Command/Database/UpgradeCommand.php +++ b/src/ChamiloLMS/Command/Database/UpgradeCommand.php @@ -227,13 +227,19 @@ class UpgradeCommand extends AbstractCommand $oldVersion = $currentVersion; foreach ($versionList as $versionItem => $versionInfo) { if (version_compare($versionItem, $currentVersion, '>') && version_compare($versionItem, $version, '<=')) { + $output->writeln("----------------------------------------------------------------"); + $output->writeln("Starting migration from version: $oldVersion to $versionItem "); + $output->writeln(""); + if (isset($versionInfo['require_update']) && $versionInfo['require_update'] == true) { //Greater than my current version $this->startMigration($oldVersion, $versionItem, $dryRun, $output); $oldVersion = $versionItem; + $output->writeln("----------------------------------------------------------------"); } else { $output->writeln("Version '$versionItem' does not need a DB migration"); } + } } $output->writeln("wow! You just finish to migrate. Too check the current status of your platform. Execute:chamilo:status"); @@ -261,7 +267,6 @@ class UpgradeCommand extends AbstractCommand */ public function startMigration($fromVersion, $toVersion, $dryRun, $output) { - $output->writeln("Starting migration from version: $fromVersion to $toVersion "); $installPath = api_get_path(SYS_CODE_PATH).'install/'; $versionInfo = $this->getAvailableVersionInfo($toVersion); @@ -273,6 +278,7 @@ class UpgradeCommand extends AbstractCommand $result = true; $output->writeln(""); $output->writeln("Executing file: '$sqlToInstall'"); + $output->writeln(''); $output->writeln("You have to select yes for the 'Chamilo Migrations'"); if ($result) { @@ -282,7 +288,11 @@ class UpgradeCommand extends AbstractCommand 'version' => $versionInfo['hook_to_version'], '--configuration' => $this->getMigrationConfigurationFile() ); + + $output->writeln("Executing migrations:migrate ".$versionInfo['hook_to_version']." --configuration=".$this->getMigrationConfigurationFile().""); + $input = new ArrayInput($arguments); + $command->run($input, $output); $output->writeln("Migration ended succesfully"); } diff --git a/src/ChamiloLMS/Migrations/Version10.php b/src/ChamiloLMS/Migrations/Version10.php index 5278767a54..95bb681f1d 100755 --- a/src/ChamiloLMS/Migrations/Version10.php +++ b/src/ChamiloLMS/Migrations/Version10.php @@ -5,6 +5,10 @@ namespace ChamiloLMS\Controller\Migrations; use Doctrine\DBAL\Migrations\AbstractMigration, Doctrine\DBAL\Schema\Schema; +/** + * Manages the migration to Chamilo 1.10 + * @package ChamiloLMS\Controller\Migrations + */ class Version10 extends AbstractMigration { public function up(Schema $schema) @@ -14,6 +18,6 @@ class Version10 extends AbstractMigration public function down(Schema $schema) { - + $this->addSql('UPDATE settings_current SET selected_value = "1.9" WHERE variable = "chamilo_database_version"'); } } \ No newline at end of file diff --git a/src/ChamiloLMS/Migrations/Version11.php b/src/ChamiloLMS/Migrations/Version11.php new file mode 100755 index 0000000000..84ef2617ac --- /dev/null +++ b/src/ChamiloLMS/Migrations/Version11.php @@ -0,0 +1,23 @@ +addSql('UPDATE settings_current SET selected_value = "1.11" WHERE variable = "chamilo_database_version"'); + } + + public function down(Schema $schema) + { + $this->addSql('UPDATE settings_current SET selected_value = "1.10" WHERE variable = "chamilo_database_version"'); + } +} \ No newline at end of file diff --git a/src/ChamiloLMS/Migrations/Version8.php b/src/ChamiloLMS/Migrations/Version8.php index 5cf6b03fed..fd8951d501 100755 --- a/src/ChamiloLMS/Migrations/Version8.php +++ b/src/ChamiloLMS/Migrations/Version8.php @@ -14,6 +14,6 @@ class Version8 extends AbstractMigration public function down(Schema $schema) { - + $this->addSql('UPDATE settings_current SET selected_value = "1.8.7" WHERE variable = "chamilo_database_version"'); } } diff --git a/src/ChamiloLMS/Migrations/Version9.php b/src/ChamiloLMS/Migrations/Version9.php index 6ab4395962..8bc2dd41aa 100755 --- a/src/ChamiloLMS/Migrations/Version9.php +++ b/src/ChamiloLMS/Migrations/Version9.php @@ -5,6 +5,10 @@ namespace ChamiloLMS\Controller\Migrations; use Doctrine\DBAL\Migrations\AbstractMigration, Doctrine\DBAL\Schema\Schema; +/** + * Manages the migration to version 1.9.0 + * @package ChamiloLMS\Controller\Migrations + */ class Version9 extends AbstractMigration { public function up(Schema $schema) @@ -14,6 +18,6 @@ class Version9 extends AbstractMigration public function down(Schema $schema) { - + $this->addSql('UPDATE settings_current SET selected_value = "1.8.8.4" WHERE variable = "chamilo_database_version"'); } } diff --git a/tests/doctrine_console/cli-config.php b/tests/doctrine_console/cli-config.php index cf06d4fd33..e71b0b6ab1 100755 --- a/tests/doctrine_console/cli-config.php +++ b/tests/doctrine_console/cli-config.php @@ -44,13 +44,15 @@ if (!empty($courseList)) { } } -$connectionOptions['main_database'] = array( - 'driver' => 'pdo_mysql', - 'dbname' => $_configuration['main_database'], - 'user' => $_configuration['db_user'], - 'password' => $_configuration['db_password'], - 'host' => $_configuration['db_host'], -); +if (isset($connectionOptions['main_database'])) { + $connectionOptions['main_database'] = array( + 'driver' => 'pdo_mysql', + 'dbname' => $_configuration['main_database'], + 'user' => $_configuration['db_user'], + 'password' => $_configuration['db_password'], + 'host' => $_configuration['db_host'], + ); +} if (isset($_configuration['statistics_database'])) { $connectionOptions['statistics_database'] = array( @@ -73,13 +75,20 @@ if (isset($_configuration['user_personal_database'])) { } $defaultConnection = array( - 'driver' => 'pdo_mysql', - 'dbname' => $_configuration['main_database'], - 'user' => $_configuration['db_user'], - 'password' => $_configuration['db_password'], - 'host' => $_configuration['db_host'], + 'driver' => 'pdo_mysql', ); +if (isset($_configuration['main_database'])) { + + $defaultConnection = array( + 'driver' => 'pdo_mysql', + 'dbname' => $_configuration['main_database'], + 'user' => $_configuration['db_user'], + 'password' => $_configuration['db_password'], + 'host' => $_configuration['db_host'], + ); +} + $em = \Doctrine\ORM\EntityManager::create($defaultConnection, $config); //Fixes some errors