/** * Handler called after the creation/update of the database schema * @param $oConfiguration Config The new configuration of the application * @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install) * @param $sCurrentVersion string Current version number of the module */ public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) { // Bug #464 - start_date was both in Ticket and Change tables // $sSourceTable = 'change'; $sSourceKeyField = 'id'; $sTargetTable = 'ticket'; $sTargetKeyField = 'id'; $sField = 'start_date'; if (CMDBSource::IsField($sSourceTable, $sField) && CMDBSource::IsField($sTargetTable, $sField) && CMDBSource::IsField($sSourceTable, $sSourceKeyField) && CMDBSource::IsField($sTargetTable, $sTargetKeyField)) { SetupPage::log_info("Issue #464 - Copying change/start_date into ticket/start_date"); $sRepair = "UPDATE `{$sTargetTable}`, `{$sSourceTable}` SET `{$sTargetTable}`.`{$sField}` = `{$sSourceTable}`.`{$sField}` WHERE `{$sTargetTable}`.`{$sField}` IS NULL AND`{$sTargetTable}`.`{$sTargetKeyField}` = `{$sSourceTable}`.`{$sSourceKeyField}`"; CMDBSource::Query($sRepair); } }
/** * Handler called after the creation/update of the database schema * @param $oConfiguration Config The new configuration of the application * @param $sPreviousVersion string PRevious version number of the module (empty string in case of first install) * @param $sCurrentVersion string Current version number of the module */ public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion) { // For each record having item_org_id unset, // get the org_id from the container object // // Prerequisite: change null into 0 (workaround to the fact that we cannot use IS NULL in OQL) SetupPage::log_info("Initializing attachment/item_org_id - null to zero"); $sTableName = MetaModel::DBGetTable('Attachment'); $sRepair = "UPDATE `{$sTableName}` SET `item_org_id` = 0 WHERE `item_org_id` IS NULL"; CMDBSource::Query($sRepair); SetupPage::log_info("Initializing attachment/item_org_id - zero to the container"); $oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE item_org_id = 0"); $oSet = new DBObjectSet($oSearch); $iUpdated = 0; while ($oAttachment = $oSet->Fetch()) { $oContainer = MetaModel::GetObject($oAttachment->Get('item_class'), $oAttachment->Get('item_id'), false, true); if ($oContainer) { $oAttachment->SetItem($oContainer, true); $iUpdated++; } } SetupPage::log_info("Initializing attachment/item_org_id - {$iUpdated} records have been adjusted"); }
/** * Helper to modify an enum value * The change is made in the datamodel definition, but the value has to be changed in the DB as well * Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation() * This helper does change ONE value at a time * * @param string $sClass A valid class name * @param string $sAttCode The enum attribute code * @param string $sFrom Original value (already INVALID in the current datamodel) * @param string $sTo New value (valid in the current datamodel) * @return void */ public static function RenameEnumValueInDB($sClass, $sAttCode, $sFrom, $sTo) { try { $sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode); $sTableName = MetaModel::DBGetTable($sOriginClass); $oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sAttCode); if ($oAttDef instanceof AttributeEnum) { $oValDef = $oAttDef->GetValuesDef(); if ($oValDef) { $aNewValues = array_keys($oValDef->GetValues(array(), "")); if (in_array($sTo, $aNewValues)) { $sEnumCol = $oAttDef->Get("sql"); $aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `{$sTableName}` WHERE Field = '{$sEnumCol}'"); if (isset($aFields[0]['Type'])) { $sColType = $aFields[0]['Type']; // Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string if (preg_match("/^enum\\(\\'(.*)\\'\\)\$/", $sColType, $aMatches)) { $aCurrentValues = explode("','", $aMatches[1]); } } if (!in_array($sFrom, $aNewValues)) { if (!in_array($sTo, $aCurrentValues)) { $sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL'; if (strtolower($sTo) == strtolower($sFrom)) { SetupPage::log_info("Changing enum in DB - {$sClass}::{$sAttCode} from '{$sFrom}' to '{$sTo}' (just a change in the case)"); $aTargetValues = array(); foreach ($aCurrentValues as $sValue) { if ($sValue == $sFrom) { $sValue = $sTo; } $aTargetValues[] = $sValue; } $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aTargetValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); } else { // 1st - Allow both values in the column definition // SetupPage::log_info("Changing enum in DB - {$sClass}::{$sAttCode} from '{$sFrom}' to '{$sTo}'"); $aAllValues = $aCurrentValues; $aAllValues[] = $sTo; $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aAllValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); // 2nd - Change the old value into the new value // $sRepair = "UPDATE `{$sTableName}` SET `{$sEnumCol}` = '{$sTo}' WHERE `{$sEnumCol}` = BINARY '{$sFrom}'"; CMDBSource::Query($sRepair); $iAffectedRows = CMDBSource::AffectedRows(); SetupPage::log_info("Changing enum in DB - {$iAffectedRows} rows updated"); // 3rd - Remove the useless value from the column definition // $aTargetValues = array(); foreach ($aCurrentValues as $sValue) { if ($sValue == $sFrom) { $sValue = $sTo; } $aTargetValues[] = $sValue; } $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aTargetValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); SetupPage::log_info("Changing enum in DB - removed useless value '{$sFrom}'"); } } } else { SetupPage::log_warning("Changing enum in DB - {$sClass}::{$sAttCode} - '{$sFrom}' is still a valid value (" . implode(', ', $aNewValues) . ")"); } } else { SetupPage::log_warning("Changing enum in DB - {$sClass}::{$sAttCode} - '{$sTo}' is not a known value (" . implode(', ', $aNewValues) . ")"); } } } } catch (Exception $e) { SetupPage::log_warning("Changing enum in DB - {$sClass}::{$sAttCode} - '{$sTo}' failed. Reason " . $e->getMessage()); } }
public static function log_info($sText) { SetupPage::log_info($sText); }
protected function log_info($sText) { SetupPage::log_info($sText); }
/** * Helper to modify an enum value * The change is made in the datamodel definition, but the value has to be changed in the DB as well * Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation() * * @param string $sClass A valid class name * @param string $sAttCode The enum attribute code * @param string $sFrom Original value (already INVALID in the current datamodel) * @param string $sTo New value (valid in the current datamodel) * @return void */ public static function RenameEnumValueInDB($sClass, $sAttCode, $sFrom, $sTo) { $sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sAttCode); $sTableName = MetaModel::DBGetTable($sOriginClass); $oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sAttCode); if ($oAttDef instanceof AttributeEnum) { $oValDef = $oAttDef->GetValuesDef(); if ($oValDef) { $aNewValues = array_keys($oValDef->GetValues(array(), "")); if (in_array($sTo, $aNewValues)) { $aAllValues = $aNewValues; $aAllValues[] = $sFrom; if (!in_array($sFrom, $aNewValues)) { $sEnumCol = $oAttDef->Get("sql"); $sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL'; if (strtolower($sTo) == strtolower($sFrom)) { SetupPage::log_info("Changing enum in DB - {$sClass}::{$sAttCode} from '{$sFrom}' to '{$sTo}' (just a change in the case)"); $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aNewValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); } else { // 1st - Allow both values in the column definition // SetupPage::log_info("Changing enum in DB - {$sClass}::{$sAttCode} from '{$sFrom}' to '{$sTo}'"); $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aAllValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); // 2nd - Change the old value into the new value // $sRepair = "UPDATE `{$sTableName}` SET `{$sEnumCol}` = '{$sTo}' WHERE `{$sEnumCol}` = BINARY '{$sFrom}'"; CMDBSource::Query($sRepair); $iAffectedRows = CMDBSource::AffectedRows(); SetupPage::log_info("Changing enum in DB - {$iAffectedRows} rows updated"); // 3rd - Remove the useless value from the column definition // $sColumnDefinition = "ENUM(" . implode(",", CMDBSource::Quote($aNewValues)) . ") {$sNullSpec}"; $sRepair = "ALTER TABLE `{$sTableName}` MODIFY `{$sEnumCol}` {$sColumnDefinition}"; CMDBSource::Query($sRepair); SetupPage::log_info("Changing enum in DB - removed useless value '{$sFrom}'"); } } else { SetupPage::log_warning("Changing enum in DB - {$sClass}::{$sAttCode} - '{$sFrom}' is still a valid value (" . implode(', ', $aNewValues) . ")"); } } else { SetupPage::log_warning("Changing enum in DB - {$sClass}::{$sAttCode} - '{$sTo}' is not a known value (" . implode(', ', $aNewValues) . ")"); } } } }
$oPage = new ajax_page(''); $oDummyController = new WizardController(''); if (is_subclass_of($sClass, 'WizardStep')) { $oStep = new $sClass($oDummyController, $sState); $sConfigFile = utils::GetConfigFilePath(); if (file_exists($sConfigFile) && !is_writable($sConfigFile) && $oStep->RequiresWritableConfig()) { $oPage->error("<b>Error:</b> the configuration file '" . $sConfigFile . "' already exists and cannot be overwritten."); $oPage->p("The wizard cannot modify the configuration file for you. If you want to upgrade " . ITOP_APPLICATION . ", make sure that the file '<b>" . realpath($sConfigFile) . "</b>' can be modified by the web server."); $oPage->output(); } else { $oStep->AsyncAction($oPage, $sActionCode, $aParams); } } $oPage->output(); break; default: throw new Exception("Error unsupported operation '{$sOperation}'"); } } catch (Exception $e) { header("HTTP/1.0 500 Internal server error."); echo "<p>An error happened while processing the installation:</p>\n"; echo '<p>' . $e . "</p>\n"; SetupPage::log_error("An error happened while processing the installation: " . $e); } if (function_exists('memory_get_peak_usage')) { if ($sOperation == 'file') { SetupPage::log_info("loading file '{$sFileName}', peak memory usage. " . memory_get_peak_usage()); } else { SetupPage::log_info("operation '{$sOperation}', peak memory usage. " . memory_get_peak_usage()); } }
protected static function DoCreateConfig($sMode, $sModulesDir, $sDBServer, $sDBUser, $sDBPwd, $sDBName, $sDBPrefix, $sUrl, $sLanguage, $aSelectedModules, $sTargetEnvironment, $bOldAddon, $sSourceDir, $sPreviousConfigFile, $sDataModelVersion, $sGraphvizPath) { $aParamValues = array('mode' => $sMode, 'db_server' => $sDBServer, 'db_user' => $sDBUser, 'db_pwd' => $sDBPwd, 'db_name' => $sDBName, 'new_db_name' => $sDBName, 'db_prefix' => $sDBPrefix, 'application_path' => $sUrl, 'language' => $sLanguage, 'graphviz_path' => $sGraphvizPath, 'selected_modules' => implode(',', $aSelectedModules)); $bPreserveModuleSettings = false; if ($sMode == 'upgrade') { try { $oOldConfig = new Config($sPreviousConfigFile); $oConfig = clone $oOldConfig; $bPreserveModuleSettings = true; } catch (Exception $e) { // In case the previous configuration is corrupted... start with a blank new one $oConfig = new Config(); } } else { $oConfig = new Config(); // To preserve backward compatibility while upgrading to 2.0.3 (when tracking_level_linked_set_default has been introduced) // the default value on upgrade differs from the default value at first install $oConfig->Set('tracking_level_linked_set_default', LINKSET_TRACKING_NONE, 'first_install'); } // Migration: force utf8_unicode_ci as the collation to make the global search // NON case sensitive $oConfig->SetDBCollation('utf8_unicode_ci'); // Final config update: add the modules $oConfig->UpdateFromParams($aParamValues, $sModulesDir, $bPreserveModuleSettings); if ($bOldAddon) { // Old version of the add-on for backward compatibility with pre-2.0 data models $oConfig->SetAddons(array('user rights' => 'addons/userrights/userrightsprofile.db.class.inc.php')); } $oConfig->Set('source_dir', $sSourceDir); // Have it work fine even if the DB has been set in read-only mode for the users $iPrevAccessMode = $oConfig->Get('access_mode'); $oConfig->Set('access_mode', ACCESS_FULL); // Record which modules are installed... $oProductionEnv = new RunTimeEnvironment($sTargetEnvironment); $oProductionEnv->InitDataModel($oConfig, true); // load data model and connect to the database $aAvailableModules = $oProductionEnv->AnalyzeInstallation(MetaModel::GetConfig(), APPROOT . $sModulesDir); if (!$oProductionEnv->RecordInstallation($oConfig, $sDataModelVersion, $aSelectedModules, $sModulesDir)) { throw new Exception("Failed to record the installation information"); } // Restore the previous access mode $oConfig->Set('access_mode', $iPrevAccessMode); // Make sure the root configuration directory exists if (!file_exists(APPCONF)) { mkdir(APPCONF); chmod(APPCONF, 0770); // RWX for owner and group, nothing for others SetupPage::log_info("Created configuration directory: " . APPCONF); } // Write the final configuration file $sConfigFile = APPCONF . ($sTargetEnvironment == '' ? 'production' : $sTargetEnvironment) . '/' . ITOP_CONFIG_FILE; $sConfigDir = dirname($sConfigFile); @mkdir($sConfigDir); @chmod($sConfigDir, 0770); // RWX for owner and group, nothing for others $oConfig->WriteToFile($sConfigFile); // try to make the final config file read-only @chmod($sConfigFile, 0444); // Read-only for owner and group, nothing for others // Ready to go !! require_once APPROOT . 'core/dict.class.inc.php'; MetaModel::ResetCache(); }