Index: branches/unlabeled/unlabeled-1.6.2/core/install.php
===================================================================
diff -u -r7471 -r7525
--- branches/unlabeled/unlabeled-1.6.2/core/install.php (.../install.php) (revision 7471)
+++ branches/unlabeled/unlabeled-1.6.2/core/install.php (.../install.php) (revision 7525)
@@ -7,6 +7,12 @@
define('FULL_PATH', realpath(dirname(__FILE__).'/..') );
define('REL_PATH', '/core');
+ /**
+ * Upgrade sqls are located using this mask
+ *
+ */
+ define('UPGRADES_FILE', FULL_PATH.'/%sinstall/upgrades.sql');
+
// print_pre($_POST);
$install_engine = new kInstallator();
@@ -73,20 +79,26 @@
'fresh_install' => Array ('check_paths', 'db_config', 'root_password', 'choose_modules', 'finish'),
'already_installed' => Array ('install_setup'),
- 'upgrade' => Array ('install_setup',/* ..., */ 'finish'),
+ 'upgrade' => Array ('install_setup', 'upgrade_modules', /* ..., */ 'finish'),
'db_reconfig' => Array ('install_setup',/* ..., */ 'finish'),
'fix_paths' => Array ('install_setup',/* ..., */ 'finish'),
);
/**
+ * Steps, that doesn't required admin to be logged-in to proceed
+ *
+ * @var Array
+ */
+ var $skipLoginSteps = Array ('root_password', 'choose_modules', 'finish', -1);
+
+ /**
* Steps, on which kApplication should not be initialized, because of missing correct db table structure
*
* @var Array
*/
+ var $skipApplicationSteps = Array ('check_paths', 'db_config'/*, 'install_setup'*/); // remove install_setup when application will work separately from install
- var $skipApplicationSteps = Array ('check_paths', 'db_config', 'install_setup'); // remove install_setup when application will work separately from install
-
/**
* Folders that should be writeable to continue installation
*
@@ -131,17 +143,24 @@
$this->currentStep = $this->GetVar('step');
+ // can't check login on steps where no application present anyways :)
+ $this->skipLoginSteps = array_unique(array_merge($this->skipLoginSteps, $this->skipApplicationSteps));
+
$this->SelectPreset();
if (!$this->currentStep) {
- // first step of current preset
- reset($this->steps[$this->stepsPreset]);
- $this->currentStep = current($this->steps[$this->stepsPreset]);
+ $this->SetFirstStep(); // sets first step of current preset
}
$this->InitStep();
}
+ function SetFirstStep()
+ {
+ reset($this->steps[$this->stepsPreset]);
+ $this->currentStep = current($this->steps[$this->stepsPreset]);
+ }
+
/**
* Selects preset to proceed based on various criteria
*
@@ -153,8 +172,12 @@
// only at installation first step
$status = $this->CheckDatabase(false);
if ($status && $this->AlreadyInstalled()) {
- $preset = 'already_installed';
- $this->currentStep = '';
+ // if already installed, then all future actions need login to work
+ $this->skipLoginSteps = Array (-1);
+ if (!$preset) {
+ $preset = 'already_installed';
+ $this->currentStep = '';
+ }
}
}
if ($preset === false) {
@@ -163,7 +186,7 @@
$this->stepsPreset = $preset;
}
-
+
function GetVar($name)
{
return isset($_REQUEST[$name]) ? $_REQUEST[$name] : false;
@@ -175,8 +198,17 @@
*/
function InitStep()
{
- $this->InitApplication();
+ $require_login = !in_array($this->currentStep, $this->skipLoginSteps);
+ $this->InitApplication($require_login);
+ if ($require_login) {
+ // step require login to proceed
+ if (!$this->Application->LoggedIn()) {
+ $this->stepsPreset = 'already_installed';
+ $this->SetFirstStep();
+ }
+ }
+
switch ($this->currentStep) {
case 'check_paths':
foreach ($this->writeableFolders as $folder_path) {
@@ -217,30 +249,43 @@
}
break;
- case 'install_setup':
- if ($this->stepsPreset == 'already_installed') {
- // if preset was not choosen, then raise error
- $this->errorMessage = 'Please select action to perform';
+ case 'upgrade_modules':
+ // get installed modules from db and compare their versions to upgrade script
+ $modules = $this->GetUpgradableModules();
+ if (!$modules) {
+ $this->currentStep = $this->GetNextStep();
}
- else {
- // if preset was choosen, then check root password entered
- $user_name = $this->GetVar('user_name');
- $user_password = $this->GetVar('user_password');
-
- if ($user_name == 'root') {
- $sql = 'SELECT VariableValue
- FROM '.$this->systemConfig['Database']['TablePrefix'].'
- WHERE VariableName = "RootPass"';
- $root_password = $this->Conn->GetOne($sql);
- $user_password = md5( md5($user_password) . 'b38');
- if ($user_password != $root_password) {
- $this->errorMessage = 'Invalid User Name or Password. If you don\'t know your username or password, contact Intechnic Support';
+ break;
+
+ case 'install_setup':
+ $next_preset = $this->Application->GetVar('next_preset');
+ if ($next_preset !== false && $this->Application->GetVar('login') == 'root') {
+ // option was choosen, then verify password & login user
+ $login_event = new kEvent('u.current:OnLogin');
+ $this->Application->HandleEvent($login_event);
+
+ if ($login_event->status == erSUCCESS) {
+ // login succeeded
+
+ if (!isset($this->steps[$next_preset])) {
+ $this->errorMessage = 'Preset "'.$next_preset.'" not yet implemented';
}
+ else {
+ $this->stepsPreset = $next_preset;
+ }
}
else {
- $this->errorMessage = 'By now only login using "root" username is supported';
+ // login failed
+ $user =& $this->Application->recallObject('u.current');
+ /* @var $user UsersItem */
+
+ $this->errorMessage = $user->GetErrorMsg('ValidateLogin').'. If you don\'t know your username or password, contact Intechnic Support';
}
}
+ else {
+ // if preset was not choosen, then raise error
+ $this->errorMessage = 'Please select action to perform';
+ }
break;
}
@@ -341,13 +386,14 @@
case 'choose_modules':
// run module install scripts
$modules = $this->Application->GetVar('modules');
- foreach ($modules as $module) {
- $install_file = MODULES_PATH.'/'.$module.'/install.php';
- if (file_exists($install_file)) {
- include_once($install_file);
+ if ($modules) {
+ foreach ($modules as $module) {
+ $install_file = MODULES_PATH.'/'.$module.'/install.php';
+ if (file_exists($install_file)) {
+ include_once($install_file);
+ }
}
}
-
// scan themes
$themes_helper =& $this->Application->recallObject('ThemesHelper');
/* @var $themes_helper kThemesHelper */
@@ -362,8 +408,50 @@
$updater->OneStepRun();
break;
+
+ case 'upgrade_modules':
+ // get installed modules from db and compare their versions to upgrade script
+ $modules = $this->Application->GetVar('modules');
+ if ($modules) {
+ $upgrade_data = $this->GetUpgradableModules();
+
+ foreach ($modules as $module_name) {
+ $module_info = $upgrade_data[$module_name];
+ $upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path']);
+
+ $sqls = file_get_contents($upgrades_file);
+ $version_mark = '# ===== v '.$module_info['FromVersion'].' =====';
+
+ $start_pos = strpos($sqls, $version_mark);
+ $sqls = substr($sqls, $start_pos);
+ $this->RunSQLText($sqls);
+
+ // after upgrade sqls are executed update version
+ $sql = 'UPDATE '.TABLE_PREFIX.'Modules
+ SET Version = "'.$module_info['ToVersion'].'"
+ WHERE Name = "'.$module_name.'"';
+ $this->Conn->Query($sql);
+ }
+ }
+ else {
+ $this->errorMessage = 'Please select module(-s) to upgrade';
+ }
+ break;
+
case 'finish':
- $this->Conn->Query('INSERT INTO '.TABLE_PREFIX.'ConfigurationValues (VariableName, VariableValue) VALUE (\'InstallFinished\', 1)');
+ // delete cache
+ $sql = 'DELETE FROM '.TABLE_PREFIX.'Cache
+ WHERE VarName IN ("config_files","configs_parsed","sections_parsed")';
+ $this->Conn->Query($sql);
+
+ // set installation finished mark
+ if ($this->Application->ConfigValue('InstallFinished') === false) {
+ $fields_hash = Array (
+ 'VariableName' => 'InstallFinished',
+ 'VariableValue' => 1,
+ );
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ConfigurationValues');
+ }
break;
}
@@ -397,11 +485,16 @@
$this->Conn->Query($sql);
}
- function InitApplication()
+ /**
+ * Initialize kApplication
+ *
+ * @param bool $force initialize in any case
+ */
+ function InitApplication($force = false)
{
- if (!in_array($this->currentStep, $this->skipApplicationSteps) && !isset($this->Application)) {
+ if (($force || !in_array($this->currentStep, $this->skipApplicationSteps)) && !isset($this->Application)) {
// step is allowed for application usage & it was not initialized in previous step
- global $debugger;
+ global $start, $debugger, $dbg_options;
include_once(FULL_PATH.'/core/kernel/startup.php');
$this->Application =& kApplication::Instance();
@@ -425,7 +518,7 @@
if (isset($this->Application)) {
$this->Application->Done();
- echo 'SID: ['.$this->Application->GetSID().']
';
+// echo 'SID: ['.$this->Application->GetSID().']
';
}
exit;
@@ -545,14 +638,32 @@
return $all_found;
}
+ /**
+ * Runs SQLs from file
+ *
+ * @param string $filename
+ * @param mixed $replace_from
+ * @param mixed $replace_to
+ */
function RunSQL($filename, $replace_from = null, $replace_to = null)
{
if (!file_exists(FULL_PATH.$filename)) {
return ;
}
$sqls = file_get_contents(FULL_PATH.$filename);
+ $this->RunSQLText($sqls, $replace_from, $replace_to);
+ }
+ /**
+ * Runs SQLs from string
+ *
+ * @param string $sqls
+ * @param mixed $replace_from
+ * @param mixed $replace_to
+ */
+ function RunSQLText(&$sqls, $replace_from = null, $replace_to = null)
+ {
$table_prefix = $this->systemConfig['Database']['TablePrefix'];
// add prefix to all tables
@@ -568,13 +679,15 @@
// replace something additionally, e.g. module root category
$sqls = str_replace($replace_from, $replace_to, $sqls);
}
-
+
+ $sqls = str_replace("\r\n", "\n", $sqls); // convert to linux line endings
+ $sqls = preg_replace("/#(.*?)\n/", '', $sqls); // remove all comments
$sqls = explode(";\n", $sqls);
foreach ($sqls as $sql) {
$sql = trim($sql);
- if (!$sql || substr($sql, 0, 1) == '#') {
- continue; // usually last line || comment
+ if (!$sql) {
+ continue; // usually last line
}
$this->Conn->Query($sql);
if ($this->Conn->getErrorCode() != 0) {
@@ -584,7 +697,7 @@
}
}
}
-
+
function ImportLanguage($lang_file)
{
$lang_file = FULL_PATH.$lang_file.'.lang';
@@ -627,6 +740,69 @@
}
/**
+ * Converts module version in format X.Y.Z to signle integer
+ *
+ * @param string $version
+ * @return int
+ */
+ function ConvertModuleVersion($version)
+ {
+ $parts = explode('.', $version);
+
+ $bin = '';
+ foreach ($parts as $part) {
+ $bin .= str_pad(decbin($part), 8, '0', STR_PAD_LEFT);
+ }
+
+ return bindec($bin);
+ }
+
+ /**
+ * Returns list of modules, that can be upgraded
+ *
+ */
+ function GetUpgradableModules()
+ {
+ $ret = Array ();
+
+ foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
+ $upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path']);
+ if (!file_exists($upgrades_file)) {
+ // no upgrade file
+ continue;
+ }
+
+ $sqls = file_get_contents($upgrades_file);
+ $versions_found = preg_match_all('/# ===== v ([\d]+\.[\d]+\.[\d]+) =====/s', $sqls, $regs);
+ if (!$versions_found) {
+ // upgrades file doesn't contain version definitions
+ continue;
+ }
+
+ $to_version = end($regs[1]);
+ $this_version = $this->ConvertModuleVersion($module_info['Version']);
+ if ($this->ConvertModuleVersion($to_version) > $this_version) {
+ // destination version is greather then current
+ foreach ($regs[1] as $version) {
+ if ($this->ConvertModuleVersion($version) > $this_version) {
+ $from_version = $version;
+ break;
+ }
+ }
+
+ $version_info = Array (
+ 'FromVersion' => $from_version,
+ 'ToVersion' => $to_version,
+ );
+
+ $ret[$module_name] = array_merge_recursive2($module_info, $version_info);
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
* Returns content to show for current step
*
* @return string