Added support for upgrading arbitrary previous 1.0.x versions (very experimental)
--- 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 '<p>ERROR: Unsupported version</p>';
+ $ui->show_footer();
+ exit;
+ }
+ if ( !isset($version_flipped[$version_target]) )
+ {
+ echo '<p>ERROR: Upgrader doesn\'t support its own version</p>';
+ $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 '<p>ERROR: Unsupported intermediate version</p>';
+ $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 "<p>ERROR: Couldn't find required schema file: $file</p>";
+ $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("<pre>$e</pre>");
+ }
+
+ $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]);
+ }
+}
+
?>
--- /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='<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="Go" style="width: 20%" /></p></form></div>' 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;
+
--- /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 @@
+
--- /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 @@
+
--- /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;
+
--- /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 @@
+
--- 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
--- 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',
--- 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 '<p>ERROR: Unsupported version</p>';
- $ui->show_footer();
- exit;
- }
- if ( !isset($version_flipped[$version_target]) )
- {
- echo '<p>ERROR: Upgrader doesn\'t support its own version</p>';
- $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 '<p>ERROR: Unsupported intermediate version</p>';
- $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 "<p>ERROR: Couldn't find required schema file: $file</p>";
- $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("<pre>$e</pre>");
- }
-
- $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 '<p>All done!</p>';
}
else