# HG changeset patch # User Dan # Date 1204996347 18000 # Node ID 6c78cc4560910736beb11559e1640712b3c80369 # Parent d8296f89ebb5ed18f764718f41e1625f94845552 Added support for upgrading arbitrary previous 1.0.x versions (very experimental) diff -r d8296f89ebb5 -r 6c78cc456091 install/includes/libenanoinstall.php --- a/install/includes/libenanoinstall.php Fri Mar 07 01:27:28 2008 -0500 +++ b/install/includes/libenanoinstall.php Sat Mar 08 12:12:27 2008 -0500 @@ -116,4 +116,124 @@ exit; } +function enano_perform_upgrade($target_branch) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + // Import version info + global $enano_versions; + // Import UI functions + global $ui; + // This is needed for upgrade abstraction + global $dbdriver; + // Main upgrade stage + + // Init vars + list($major_version, $minor_version) = explode('.', installer_enano_version()); + $installer_branch = "$major_version.$minor_version"; + + $version_flipped = array_flip($enano_versions[$target_branch]); + $version_curr = enano_version(); + // Change this to be the last version in the current branch. + // If we're just upgrading within this branch, use the version the installer library + // reports to us. Else, use the latest in the old (current target) branch. + // $version_target = installer_enano_version(); + $version_target = ( $target_branch === $installer_branch ) ? installer_enano_version() : $enano_versions[$target_branch][ count($enano_versions[$target_branch]) - 1 ]; + + // Calculate which scripts to run + if ( !isset($version_flipped[$version_curr]) ) + { + echo '

ERROR: Unsupported version

'; + $ui->show_footer(); + exit; + } + if ( !isset($version_flipped[$version_target]) ) + { + echo '

ERROR: Upgrader doesn\'t support its own version

'; + $ui->show_footer(); + exit; + } + $upg_queue = array(); + for ( $i = $version_flipped[$version_curr]; $i < $version_flipped[$version_target]; $i++ ) + { + if ( !isset($enano_versions[$target_branch][$i + 1]) ) + { + echo '

ERROR: Unsupported intermediate version

'; + $ui->show_footer(); + exit; + } + $ver_this = $enano_versions[$target_branch][$i]; + $ver_next = $enano_versions[$target_branch][$i + 1]; + $upg_queue[] = array($ver_this, $ver_next); + } + + // Verify that all upgrade scripts are usable + foreach ( $upg_queue as $verset ) + { + $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql"; + if ( !file_exists($file) ) + { + echo "

ERROR: Couldn't find required schema file: $file

"; + $ui->show_footer(); + exit; + } + } + // Perform upgrade + foreach ( $upg_queue as $verset ) + { + $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql"; + try + { + $parser = new SQL_Parser($file); + } + catch(Exception $e) + { + die("
$e
"); + } + + $parser->assign_vars(array( + 'TABLE_PREFIX' => table_prefix + )); + + $sql_list = $parser->parse(); + // Check for empty schema file + if ( $sql_list[0] === ';' && count($sql_list) == 1 ) + { + // It's empty, report success for this version + // See below for explanation of why setConfig() is called here + setConfig('enano_version', $verset[1]); + continue; + } + + foreach ( $sql_list as $sql ) + { + // check for '@' operator on query + if ( substr($sql, 0, 1) == '@' ) + { + // Yes - perform query but don't check for errors + $db->sql_query($sql); + } + else + { + // Perform as normal + if ( !$db->sql_query($sql) ) + $db->_die(); + } + } + + // Is there an additional script (logic) to be run after the schema? + $postscript = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}.php"; + if ( file_exists($postscript) ) + @include($postscript); + + // The advantage of calling setConfig on the system version here? + // Simple. If the upgrade fails, it will pick up from the last + // version, not try to start again from the beginning. This will + // still cause errors in most cases though. Eventually we probably + // need some sort of query-numbering system that tracks in-progress + // upgrades. + + setConfig('enano_version', $verset[1]); + } +} + ?> diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.0-1.0.1-mysql.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/1.0-1.0.1-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -0,0 +1,16 @@ +-- Enano CMS +-- Upgrade schema - Enano 1.0 - 1.0.1 + +-- Fix for obnoxious $_GET issue +UPDATE {{TABLE_PREFIX}}sidebar SET block_type=1,block_content='

$INPUT_AUTH$

' WHERE block_name='Search' AND item_id=4; +-- Added on advice from Neal +-- Remember that 1 = AUTH_DENY. +INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES(2,1,'Memberlist','Special','read=1;mod_misc=1;upload_files=1;upload_new_version=1;create_page=1;edit_acl=1;'); +-- Bugfix for MySQL 5.0.45, see http://forum.enanocms.org/viewtopic.php?f=5&t=8 +ALTER TABLE {{TABLE_PREFIX}}pages MODIFY COLUMN delvote_ips text DEFAULT NULL; +CREATE TABLE {{TABLE_PREFIX}}page_groups( pg_id mediumint(8) NOT NULL auto_increment, pg_type tinyint(2) NOT NULL DEFAULT 1, pg_name varchar(255) NOT NULL DEFAULT '', pg_target varchar(255) DEFAULT NULL, PRIMARY KEY ( pg_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; +CREATE TABLE {{TABLE_PREFIX}}page_group_members( pg_member_id int(12) NOT NULL auto_increment, pg_id mediumint(8) NOT NULL, page_id varchar(63) NOT NULL, namespace varchar(63) NOT NULL DEFAULT 'Article', PRIMARY KEY ( pg_member_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; +CREATE TABLE {{TABLE_PREFIX}}tags( tag_id int(12) NOT NULL auto_increment, tag_name varchar(63) NOT NULL DEFAULT 'bla', page_id varchar(255) NOT NULL, namespace varchar(255) NOT NULL, user mediumint(8) NOT NULL DEFAULT 1, PRIMARY KEY ( tag_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; +UPDATE {{TABLE_PREFIX}}acl SET rules=CONCAT(rules,'tag_create=4;tag_delete_own=4;tag_delete_other=4;') WHERE target_type=1 AND target_id=2; +DELETE FROM {{TABLE_PREFIX}}search_cache; + diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.0.1-1.0.2b1-mysql.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/1.0.1-1.0.2b1-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -0,0 +1,1 @@ + diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.0.2-1.0.3-mysql.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/1.0.2-1.0.3-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -0,0 +1,1 @@ + diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.0.2b1-1.0.2-mysql.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/1.0.2b1-1.0.2-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -0,0 +1,29 @@ +-- Enano CMS +-- Upgrade schema - Enano 1.0.2 beta 1 - 1.0.2 release + +-- This is really optional, but could reduce confusion if regex page groups get truncated for no apparent reason. +ALTER TABLE {{TABLE_PREFIX}}page_groups MODIFY COLUMN pg_target text DEFAULT NULL; + +-- I have no idea how or why, but the f'ing index didn't get created for who-knows-how-many releases. +-- We'll attempt to create it here, but don't die if it fails +@ALTER TABLE {{TABLE_PREFIX}}page_text ENGINE = MYISAM, COLLATE = utf8_bin, CHARSET = utf8; +ALTER TABLE {{TABLE_PREFIX}}search_index CHARSET = utf8, COLLATE = utf8_bin, MODIFY COLUMN word varchar(64) NOT NULL; + +-- The search cache is no longer needed because of the new unified search engine (it's too f'ing fast to need a cache :-D) +@DROP TABLE {{TABLE_PREFIX}}search_cache; + +-- Yes, it appears we need pages with names this long after all +ALTER TABLE {{TABLE_PREFIX}}pages MODIFY COLUMN urlname varchar(255), MODIFY COLUMN name varchar(255); + +-- Make page_text a little more efficient to deal with +ALTER TABLE {{TABLE_PREFIX}}page_text MODIFY COLUMN page_id varchar(255), MODIFY COLUMN namespace varchar(63), MODIFY COLUMN page_text longtext; + +-- Now recreate the fulltext index +@CREATE FULLTEXT INDEX {{TABLE_PREFIX}}page_search_idx ON {{TABLE_PREFIX}}page_text(page_id, namespace, page_text); + +-- Addition of new file types +UPDATE {{TABLE_PREFIX}}config SET config_value='cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' WHERE config_name = 'allowed_mime_types' AND config_value='cbf:len=168;crc=c3dcad3f;data=0[1],1[4],0[3],1[1],0[2],1[1],0[11],1[1],0[7],1[1],0[9],1[1],0[6],1[3],0[10],1[1],0[2],1[2],0[1],1[1],0[1],1[2],0[6],1[3],0[1],1[1],0[2],1[4],0[1],1[2],0[3],1[1],0[4],1[2],0[26],1[5],0[6],1[2],0[2],1[1],0[4],1[1],0[10],1[2],0[1],1[1],0[6]|end'; + +-- Reinforcement of "stable release" mentality +@UPDATE {{TABLE_PREFIX}}users SET theme='oxygen', style='bleu' WHERE user_id = 2; + diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.0.3-1.0.4-mysql.sql --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install/schemas/upgrade/1.0.3-1.0.4-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -0,0 +1,1 @@ + diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.1.1-1.1.2-mysql.sql --- a/install/schemas/upgrade/1.1.1-1.1.2-mysql.sql Fri Mar 07 01:27:28 2008 -0500 +++ b/install/schemas/upgrade/1.1.1-1.1.2-mysql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -4,8 +4,8 @@ ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN log_id int(15) NOT NULL auto_increment, ADD PRIMARY KEY ( log_id ); ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN is_draft tinyint(1) NOT NULL DEFAULT 0; -ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int(12) UNSIGNED NOT NULL DEFAULT 1, - ADD COLUMN user_timezone int(12) UNSIGNED NOT NULL DEFAULT 0; +ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int(12) UNSIGNED NOT NULL DEFAULT 1; +@ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_timezone int(12) UNSIGNED NOT NULL DEFAULT 0; ALTER TABLE {{TABLE_PREFIX}}tags CHANGE user user_id mediumint(8) NOT NULL DEFAULT 1; ALTER TABLE {{TABLE_PREFIX}}themes diff -r d8296f89ebb5 -r 6c78cc456091 install/schemas/upgrade/1.1.1-1.1.2-postgresql.sql --- a/install/schemas/upgrade/1.1.1-1.1.2-postgresql.sql Fri Mar 07 01:27:28 2008 -0500 +++ b/install/schemas/upgrade/1.1.1-1.1.2-postgresql.sql Sat Mar 08 12:12:27 2008 -0500 @@ -4,8 +4,9 @@ ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN log_id SERIAL, ADD PRIMARY KEY ( log_id ); ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN is_draft smallint NOT NULL DEFAULT 0; -ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int NOT NULL DEFAULT 1, - ADD COLUMN user_timezone int NOT NULL DEFAULT 0; +ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int NOT NULL DEFAULT 1; +@ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_timezone int NOT NULL DEFAULT 0; + ALTER TABLE {{TABLE_PREFIX}}themes ADD COLUMN group_list text DEFAULT NULL, ADD COLUMN group_policy varchar(5) NOT NULL DEFAULT 'deny', diff -r d8296f89ebb5 -r 6c78cc456091 install/upgrade.php --- a/install/upgrade.php Fri Mar 07 01:27:28 2008 -0500 +++ b/install/upgrade.php Sat Mar 08 12:12:27 2008 -0500 @@ -16,8 +16,10 @@ define('IN_ENANO', 1); -// The list of versions in THIS BRANCH, in chronological order. -$enano_versions = array('1.1.1', '1.1.2', '1.1.3'); +// The list of versions in THIS AND PREVIOUS branches, in chronological order. +$enano_versions = array(); +$enano_versions['1.0'] = array('1.0', '1.0.1', '1.0.2b1', '1.0.2', '1.0.3', '1.0.4'); +$enano_versions['1.1'] = array('1.1.1', '1.1.2', '1.1.3'); // Turn on every imaginable API hack to make common load on older databases define('IN_ENANO_UPGRADE', 1); @@ -25,9 +27,11 @@ define('ENANO_ALLOW_LOAD_NOLANG', 1); @ini_set('display_errors', 'on'); -require('includes/sql_parse.php'); +// Load installer files +require_once('includes/sql_parse.php'); +require_once('includes/common.php'); +require_once('includes/libenanoinstall.php'); -require_once('includes/common.php'); // when the installer's common is loaded, it runs chdir() to the ENANO_ROOT, thus making this Enano's common.php require_once('includes/common.php'); @ini_set('display_errors', 'on'); @@ -153,10 +157,43 @@ if ( isset($_GET['stage']) && @$_GET['stage'] == 'pimpmyenano' ) { + /* + HOW DOES ENANO'S UPGRADER WORK? + + Versions of Enano are organized into branches and then specific versions by + version number. The upgrader works by using a list of known version numbers + and then systematically executing upgrade schemas for each version. + + When the user requests an upgrade, the first thing performed is a migration + check, which verifies that they are within the right branch. If they are not + within the right branch the upgrade framework will load a migration script + which will define a function named MIGRATE(). Performing more than one + migration in one pass will probably never be supported. How that works for + UX in 1.3.x/1.4.x I know not yet. + + After performing any necessary branch migrations, the framework will perform + any upgrades within the target branch, which is the first two parts + (delimited by periods) of the installer's version number defined in the + installer's common.php. + + enano_perform_upgrade() will only do upgrades. Not migrations. The two as + illustrated within this installer are very different. + */ + // Do we need to run the migration first? - if ( substr(enano_version(), 0, 4) != '1.1.' ) + list($major_version, $minor_version) = explode('.', enano_version()); + $current_branch = "$major_version.$minor_version"; + + list($major_version, $minor_version) = explode('.', installer_enano_version()); + $target_branch = "$major_version.$minor_version"; + + if ( $target_branch != $current_branch ) { - require(ENANO_ROOT . '/install/upgrade/migration/1.0-1.1.php'); + // First upgrade to the latest revision of the current branch + enano_perform_upgrade($current_branch); + // Branch migration could be tricky and is often highly specific between + // major branches, so just include a custom migration script. + require(ENANO_ROOT . "/install/schemas/upgrade/migration/{$current_branch}-{$target_branch}.php"); $result = MIGRATE(); if ( !$result ) { @@ -165,90 +202,10 @@ exit; } } - // Main upgrade stage - - // Init vars - $version_flipped = array_flip($enano_versions); - $version_curr = enano_version(); - $version_target = installer_enano_version(); - - // Calculate which scripts to run - if ( !isset($version_flipped[$version_curr]) ) - { - echo '

ERROR: Unsupported version

'; - $ui->show_footer(); - exit; - } - if ( !isset($version_flipped[$version_target]) ) - { - echo '

ERROR: Upgrader doesn\'t support its own version

'; - $ui->show_footer(); - exit; - } - $upg_queue = array(); - for ( $i = $version_flipped[$version_curr]; $i < $version_flipped[$version_target]; $i++ ) - { - if ( !isset($enano_versions[$i + 1]) ) - { - echo '

ERROR: Unsupported intermediate version

'; - $ui->show_footer(); - exit; - } - $ver_this = $enano_versions[$i]; - $ver_next = $enano_versions[$i + 1]; - $upg_queue[] = array($ver_this, $ver_next); - } - // Verify that all upgrade scripts are usable - foreach ( $upg_queue as $verset ) - { - $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql"; - if ( !file_exists($file) ) - { - echo "

ERROR: Couldn't find required schema file: $file

"; - $ui->show_footer(); - exit; - } - } - // Perform upgrade - foreach ( $upg_queue as $verset ) - { - $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql"; - try - { - $parser = new SQL_Parser($file); - } - catch(Exception $e) - { - die("
$e
"); - } - - $parser->assign_vars(array( - 'TABLE_PREFIX' => table_prefix - )); + // Do the actual upgrade + enano_perform_upgrade($target_branch); - $sql_list = $parser->parse(); - - foreach ( $sql_list as $sql ) - { - if ( !$db->sql_query($sql) ) - $db->_die(); - } - - // Is there an additional script (logic) to be run after the schema? - $postscript = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}.php"; - if ( file_exists($postscript) ) - @include($postscript); - - // The advantage of calling setConfig on the system version here? - // Simple. If the upgrade fails, it will pick up from the last - // version, not try to start again from the beginning. This will - // still cause errors in most cases though. Eventually we probably - // need some sort of query-numbering system that tracks in-progress - // upgrades. - - setConfig('enano_version', $verset[1]); - } echo '

All done!

'; } else