Added support for upgrading arbitrary previous 1.0.x versions (very experimental)
authorDan
Sat, 08 Mar 2008 12:12:27 -0500
changeset 494 6c78cc456091
parent 493 d8296f89ebb5
child 495 00f5cd31217a
Added support for upgrading arbitrary previous 1.0.x versions (very experimental)
install/includes/libenanoinstall.php
install/schemas/upgrade/1.0-1.0.1-mysql.sql
install/schemas/upgrade/1.0.1-1.0.2b1-mysql.sql
install/schemas/upgrade/1.0.2-1.0.3-mysql.sql
install/schemas/upgrade/1.0.2b1-1.0.2-mysql.sql
install/schemas/upgrade/1.0.3-1.0.4-mysql.sql
install/schemas/upgrade/1.1.1-1.1.2-mysql.sql
install/schemas/upgrade/1.1.1-1.1.2-postgresql.sql
install/upgrade.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 '<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