]> gitweb.fluxo.info Git - lorea/elgg.git/commitdiff
Fixes #1433, #2183. Upgrades are now tracked and will be run if needed regardless...
authorbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>
Fri, 18 Feb 2011 00:46:54 +0000 (00:46 +0000)
committerbrettp <brettp@36083f99-b078-4883-b0ff-0f9b5a30f544>
Fri, 18 Feb 2011 00:46:54 +0000 (00:46 +0000)
git-svn-id: http://code.elgg.org/elgg/trunk@8277 36083f99-b078-4883-b0ff-0f9b5a30f544

engine/lib/database.php
engine/lib/deprecated-1.8.php
engine/lib/upgrades/create_upgrade.php [new file with mode: 0644]
engine/lib/version.php
install/ElggInstaller.php
upgrade.php

index b2cc5ca292d744d4254ec65f0c96c726b8638440..fa5b4a894e36b7b40566f3f675ea28412e07dc48 100644 (file)
@@ -628,70 +628,6 @@ function run_sql_script($scriptlocation) {
        }
 }
 
-/**
- * Upgrade the database schema in an ordered sequence.
- *
- * Executes all upgrade files in elgg/engine/schema/upgrades/ in sequential order.
- * Upgrade files must be in the standard Elgg release format of YYYYMMDDII.sql
- * where II is an incrementor starting from 01.
- *
- * Files that are < $version will be ignored.
- *
- * @warning Plugin authors should not call this function directly.
- *
- * @param int    $version The version you are upgrading from in the format YYYYMMDDII.
- * @param string $fromdir Optional directory to load upgrades from. default: engine/schema/upgrades/
- * @param bool   $quiet   If true, suppress all error messages. Only use for the upgrade from <=1.6.
- *
- * @return bool
- * @see upgrade.php
- * @see version.php
- */
-function db_upgrade($version, $fromdir = "", $quiet = FALSE) {
-       global $CONFIG;
-
-       $version = (int) $version;
-
-       if (!$fromdir) {
-               $fromdir = $CONFIG->path . 'engine/schema/upgrades/';
-       }
-
-       if ($handle = opendir($fromdir)) {
-               $sqlupgrades = array();
-
-               while ($sqlfile = readdir($handle)) {
-                       if (!is_dir($fromdir . $sqlfile)) {
-                               if (preg_match('/^([0-9]{10})\.(sql)$/', $sqlfile, $matches)) {
-                                       $sql_version = (int) $matches[1];
-                                       if ($sql_version > $version) {
-                                               $sqlupgrades[] = $sqlfile;
-                                       }
-                               }
-                       }
-               }
-
-               asort($sqlupgrades);
-
-               if (sizeof($sqlupgrades) > 0) {
-                       foreach ($sqlupgrades as $sqlfile) {
-
-                               // hide all errors.
-                               if ($quiet) {
-                                       try {
-                                               run_sql_script($fromdir . $sqlfile);
-                                       } catch (DatabaseException $e) {
-                                               error_log($e->getmessage());
-                                       }
-                               } else {
-                                       run_sql_script($fromdir . $sqlfile);
-                               }
-                       }
-               }
-       }
-
-       return TRUE;
-}
-
 /**
  * Sanitise a string for database use, but with the option of escaping extra characters.
  *
index 76abc5c95528b1861de5bd9cbae735dddd1ac293..3f65fb58e66b7c4d06ebf56e09a8215df8ea0db9 100644 (file)
@@ -3808,7 +3808,7 @@ function register_metadata_url_handler($function, $extender_name = "all") {
 }
 
 /**
- * 
+ *
  * @deprecated 1.8 Use {@link elgg_register_relationship_url_handler()}
  */
 function register_relationship_url_handler($function_name, $relationship_type = "all") {
@@ -4335,3 +4335,71 @@ function display_widget(ElggObject $widget) {
        elgg_deprecated_notice("display_widget() was been deprecated. Use elgg_view_entity().", 1.8);
        return elgg_view_entity($widget);
 }
+
+
+/**
+ * Upgrade the database schema in an ordered sequence.
+ *
+ * Executes all upgrade files in elgg/engine/schema/upgrades/ in sequential order.
+ * Upgrade files must be in the standard Elgg release format of YYYYMMDDII.sql
+ * where II is an incrementor starting from 01.
+ *
+ * Files that are < $version will be ignored.
+ *
+ * @warning Plugin authors should not call this function directly.
+ *
+ * @param int    $version The version you are upgrading from in the format YYYYMMDDII.
+ * @param string $fromdir Optional directory to load upgrades from. default: engine/schema/upgrades/
+ * @param bool   $quiet   If true, suppress all error messages. Only use for the upgrade from <=1.6.
+ *
+ * @return bool
+ * @see upgrade.php
+ * @see version.php
+ * @deprecated 1.8 Use PHP upgrades for sql changes.
+ */
+function db_upgrade($version, $fromdir = "", $quiet = FALSE) {
+       global $CONFIG;
+
+       elgg_deprecated_notice('db_upgrade() is deprecated by using PHP upgrades.', 1.8);
+
+       $version = (int) $version;
+
+       if (!$fromdir) {
+               $fromdir = $CONFIG->path . 'engine/schema/upgrades/';
+       }
+
+       if ($handle = opendir($fromdir)) {
+               $sqlupgrades = array();
+
+               while ($sqlfile = readdir($handle)) {
+                       if (!is_dir($fromdir . $sqlfile)) {
+                               if (preg_match('/^([0-9]{10})\.(sql)$/', $sqlfile, $matches)) {
+                                       $sql_version = (int) $matches[1];
+                                       if ($sql_version > $version) {
+                                               $sqlupgrades[] = $sqlfile;
+                                       }
+                               }
+                       }
+               }
+
+               asort($sqlupgrades);
+
+               if (sizeof($sqlupgrades) > 0) {
+                       foreach ($sqlupgrades as $sqlfile) {
+
+                               // hide all errors.
+                               if ($quiet) {
+                                       try {
+                                               run_sql_script($fromdir . $sqlfile);
+                                       } catch (DatabaseException $e) {
+                                               error_log($e->getmessage());
+                                       }
+                               } else {
+                                       run_sql_script($fromdir . $sqlfile);
+                               }
+                       }
+               }
+       }
+
+       return TRUE;
+}
\ No newline at end of file
diff --git a/engine/lib/upgrades/create_upgrade.php b/engine/lib/upgrades/create_upgrade.php
new file mode 100644 (file)
index 0000000..9575ada
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Creates an upgrade file for Elgg.
+ *
+ * Run this from the command line:
+ *     php create_upgrade.php upgrade_name
+ */
+
+error_reporting(E_NOTICE);
+
+// only allow from the command line.
+if (php_sapi_name() != 'cli') {
+       die('Upgrades can only be created from the command line.');
+}
+
+if (count($argv) < 2) {
+       elgg_create_upgrade_show_usage('No upgrade name.');
+}
+
+$name = $argv[1];
+
+if (strlen($name) > 24) {
+       elgg_create_upgrade_show_usage('Upgrade names cannot be longer than 24 characters.');
+}
+
+require_once '../../../version.php';
+require_once '../elgglib.php';
+$upgrade_path = dirname(__FILE__);
+
+$upgrade_name = strtolower($name);
+$upgrade_name = str_replace(array(' ', '-'), '_', $upgrade_name);
+$upgrade_release = str_replace(array(' ', '-'), '_', $release);
+$time = time();
+$upgrade_rnd = substr(md5($time), 0, 16);
+$upgrade_date = date('Ymd', $time);
+
+// determine the inc count
+$upgrade_inc = 0;
+$files = elgg_get_file_list($upgrade_path);
+sort($files);
+
+foreach ($files as $filename) {
+       $filename = basename($filename);
+       $date = (int)substr($filename, 0, 8);
+       $inc = (int)substr($filename, 8, 2);
+
+       if ($upgrade_date == $date) {
+               if ($inc >= $upgrade_inc) {
+                       $upgrade_inc = $inc + 1;
+               }
+       }
+}
+
+// zero-pad
+// if there are more than 10 upgrades in a day, someone needs talking to.
+if ($upgrade_inc < 10) {
+       $upgrade_inc = "0$upgrade_inc";
+}
+
+// make filename
+if (substr($release, 0, 3) == '1.7') {
+       // 1.7 upgrades are YYYYMMDDXX
+       $upgrade_name = $upgrade_date . $upgrade_inc . '.php';
+} else {
+       // 1.8+ upgrades are YYYYMMDDXX-release-friendly_name-rnd
+       $upgrade_name = $upgrade_date . $upgrade_inc . "-$upgrade_release-$name-$upgrade_rnd.php";
+}
+
+$upgrade_file = $upgrade_path . '/' . $upgrade_name;
+
+if (is_file($upgrade_file)) {
+       elgg_create_upgrade_show_usage("Upgrade file $upgrade_file already exists. This script has failed you.");
+}
+
+$upgrade_code = <<<___UPGRADE
+<?php
+/**
+ * Elgg $version upgrade $date$inc
+ * $name
+ */
+
+// upgrade code here.
+
+___UPGRADE;
+
+$h = fopen($upgrade_file, 'wb');
+
+if (!$h) {
+       die("Could not open file $upgrade_file");
+}
+
+if (!fputs($h, $upgrade_code)) {
+       die("Could not write to $upgrade_file");
+} else {
+       echo "\nCreated file $upgrade_name.  Add your upgrade code there.\n\n";
+}
+
+fclose($h);
+
+
+/**
+ * Shows the usage for the create_upgrade script and dies().
+ *
+ * @param string $msg Optional message to display
+ * @return void
+ */
+function elgg_create_upgrade_show_usage($msg = '') {
+       $text = <<<___MSG
+$msg
+
+Example:
+       php create_upgrade.php my_upgrade
+
+___MSG;
+
+       die($text);
+}
\ No newline at end of file
index 4ffe85bc51343e0ab072b5e8ff8ee7a998ba9995..60ae2c9735e96dd28924c30d08ce464ba1cecda1 100644 (file)
@@ -19,47 +19,151 @@ function upgrade_code($version, $quiet = FALSE) {
        global $CONFIG;
 
        $version = (int) $version;
+       $upgrade_path = elgg_get_config('path') . 'engine/lib/upgrades/';
+       $processed_upgrades = unserialize(datalist_get('processed_upgrades'));
+       // the day we started the new upgrade names
+       $upgrade_epoch = 2011021700;
 
-       if ($handle = opendir($CONFIG->path . 'engine/lib/upgrades/')) {
-               $upgrades = array();
-
-               while ($updatefile = readdir($handle)) {
-                       // Look for upgrades and add to upgrades list
-                       if (!is_dir($CONFIG->path . 'engine/lib/upgrades/' . $updatefile)) {
-                               if (preg_match('/^([0-9]{10})\.(php)$/', $updatefile, $matches)) {
-                                       $core_version = (int) $matches[1];
-                                       if ($core_version > $version) {
-                                               $upgrades[] = $updatefile;
-                                       }
+       if (!$processed_upgrades) {
+               $processed_upgrades = array();
+       }
+
+       $upgrades = array();
+
+       $upgrade_files = elgg_get_upgrade_files($upgrade_path);
+
+       if ($upgrade_files === false) {
+               return false;
+       }
+
+       // bootstrap into the new upgrade system.
+       // can't do this in an upgrade because we need to check for 2010050701,
+       // which would already have been run by then.
+       if ($version < $upgrade_epoch) {
+               foreach ($upgrade_files as $upgrade_file) {
+                       $upgrade_version = elgg_get_upgrade_file_version($upgrade_file);
+
+                       // the upgrade that made life difficult
+                       // the only way to test if we're upgrading from 1.7 to 1.8 or within 1.8
+                       // is to test for the the walled_garden config option, which
+                       // 2010050701 explicitly sets
+                       if ($upgrade_version == 2010050701) {
+                               $db_prefix = elgg_get_config('dbprefix');
+                               $site_guid = elgg_get_config('site_guid');
+                               $q = "SELECT value FROM {$db_prefix}config
+                                       WHERE name = 'walled_garden' AND site_guid = {$site_guid}";
+                               $result = get_data_row($q);
+                               if (!$result) {
+                                       $upgrades[] = $upgrade_file;
                                }
+
+                               continue;
+                       } elseif ($version < $upgrade_version) {
+                               $upgrades[] = $upgrade_file;
+                       } else {
+                               // all of the upgrades before the epoch have been run except one...
+                               $processed_upgrades[] = $upgrade_file;
                        }
                }
+       } else {
+               // add any upgrades that haven't been run to the upgrades list
+               $upgrades = elgg_get_unprocessed_upgrades($upgrade_files, $processed_upgrades);
+       }
+
+       // Sort and execute
+       ksort($upgrades);
+
+       foreach ($upgrades as $upgrade) {
+               $upgrade_version = elgg_get_upgrade_file_version($upgrade);
+               $success = true;
 
-               // Sort and execute
-               asort($upgrades);
-
-               if (sizeof($upgrades) > 0) {
-                       foreach ($upgrades as $upgrade) {
-                               // hide all errors.
-                               if ($quiet) {
-                                       // hide include errors as well as any exceptions that might happen
-                                       try {
-                                               if (!@include($CONFIG->path . 'engine/lib/upgrades/' . $upgrade)) {
-                                                       error_log($e->getmessage());
-                                               }
-                                       } catch (Exception $e) {
-                                               error_log($e->getmessage());
-                                       }
-                               } else {
-                                       include($CONFIG->path . 'engine/lib/upgrades/' . $upgrade);
+               // hide all errors.
+               if ($quiet) {
+                       // hide include errors as well as any exceptions that might happen
+                       try {
+                               if (!@include("$upgrade_path/$upgrade")) {
+                                       $success = false;
+                                       error_log($e->getmessage());
                                }
+                       } catch (Exception $e) {
+                               $success = false;
+                               error_log($e->getmessage());
+                       }
+               } else {
+                       if (!include("$upgrade_path/$upgrade")) {
+                               $success = false;
                        }
                }
 
-               return TRUE;
+               if ($success) {
+                       // incrementally set upgrade so we know where to start if something fails.
+                       $processed_upgrades[] = $upgrade;
+
+                       // don't set the version to a lower number in instances where an upgrade
+                       // has been merged from a lower version
+                       if ($upgrade_version > $version) {
+                               datalist_set('version', $upgrade_version);
+                       }
+
+                       $processed_upgrades = array_unique($processed_upgrades);
+                       datalist_set('processed_upgrades', serialize($processed_upgrades));
+               } else {
+                       return false;
+               }
        }
 
-       return FALSE;
+       return true;
+}
+
+/**
+ * Returns the version of the upgrade filename.
+ *
+ * @param string $filename The upgrade filename. No full path.
+ * @return int|false
+ * @since 1.8
+ */
+function elgg_get_upgrade_file_version($filename) {
+       preg_match('/^([0-9]{10})([\.a-z0-9-_]+)?\.(php)$/i', $filename, $matches);
+
+       if (isset($matches[1])) {
+               return (int) $matches[1];
+       }
+
+       return false;
+}
+
+/**
+ * Returns a list of upgrade files relative to the $upgrade_path dir.
+ *
+ * @param string $upgrade_path The up
+ * @return array|false
+ */
+function elgg_get_upgrade_files($upgrade_path = null) {
+       if (!$upgrade_path) {
+               $upgrade_path = elgg_get_config('path') . 'engine/lib/upgrades/';
+       }
+       $upgrade_path = sanitise_filepath($upgrade_path);
+       $handle = opendir($upgrade_path);
+
+       if (!$handle) {
+               return false;
+       }
+
+       $upgrade_files = array();
+
+       while ($upgrade_file = readdir($handle)) {
+               // make sure this is a wellformed upgrade.
+               if (is_dir($upgrade_path . '$upgrade_file')) {
+                       continue;
+               }
+               $upgrade_version = elgg_get_upgrade_file_version($upgrade_file);
+               if (!$upgrade_version) {
+                       continue;
+               }
+               $upgrade_files[] = $upgrade_file;
+       }
+
+       return $upgrade_files;
 }
 
 /**
@@ -81,6 +185,30 @@ function get_version($humanreadable = false) {
        return FALSE;
 }
 
+/**
+ * Checks if any upgrades need to be run.
+ *
+ * @param null|array $upgrade_files      Optional upgrade files
+ * @param null|array $processed_upgrades Optional processed upgrades
+ *
+ * @return array()
+ */
+function elgg_get_unprocessed_upgrades($upgrade_files = null, $processed_upgrades = null) {
+       if ($upgrade_files === null) {
+               $upgrade_files = elgg_get_upgrade_files();
+       }
+
+       if ($processed_upgrades === null) {
+               $processed_upgrades = unserialize(datalist_get('processed_upgrades'));
+               if (!is_array($processed_upgrades)) {
+                       $processed_upgrades = array();
+               }
+       }
+
+       $unprocessed = array_diff($upgrade_files, $processed_upgrades);
+       return $unprocessed;
+}
+
 /**
  * Determines whether or not the database needs to be upgraded.
  *
@@ -114,23 +242,20 @@ function version_upgrade() {
        // See http://trac.elgg.org/elgg/ticket/1432 for more.
        $quiet = !$dbversion;
 
-       // Upgrade database
-       if (db_upgrade($dbversion, '', $quiet)) {
-               system_message(elgg_echo('upgrade:db'));
-       }
+       // Note: Database upgrades are deprecated as of 1.8.  Use code upgrades.  See #1433
 
-       // Upgrade core
        if (upgrade_code($dbversion, $quiet)) {
                system_message(elgg_echo('upgrade:core'));
-       }
 
-       // Now we trigger an event to give the option for plugins to do something
-       $upgrade_details = new stdClass;
-       $upgrade_details->from = $dbversion;
-       $upgrade_details->to = get_version();
+               // Now we trigger an event to give the option for plugins to do something
+               $upgrade_details = new stdClass;
+               $upgrade_details->from = $dbversion;
+               $upgrade_details->to = get_version();
+
+               elgg_trigger_event('upgrade', 'upgrade', $upgrade_details);
 
-       elgg_trigger_event('upgrade', 'upgrade', $upgrade_details);
+               return true;
+       }
 
-       // Update the version
-       datalist_set('version', get_version());
+       return false;
 }
index 7b3fbb9ec6253759ab61418ebcaf15c9b37cf1f6..fc0eff0ab7f0c2e19ffd26f6d92df623cbd5bdc3 100644 (file)
@@ -551,7 +551,7 @@ class ElggInstaller {
        protected function getNextStepUrl($currentStep) {
                global $CONFIG;
                $nextStep = $this->getNextStep($currentStep);
-               return elgg_get_site_url()."install.php?step=$nextStep";
+               return elgg_get_site_url() . "install.php?step=$nextStep";
        }
 
        /**
@@ -1030,7 +1030,7 @@ class ElggInstaller {
                require_once(dirname(__FILE__) . "/ElggRewriteTester.php");
 
                $tester = new ElggRewriteTester();
-               $url = elgg_get_site_url()."rewrite.php";
+               $url = elgg_get_site_url() . "rewrite.php";
                $report['rewrite'] = array($tester->run($url, $CONFIG->path));
        }
 
@@ -1304,6 +1304,10 @@ class ElggInstaller {
                datalist_set('default_site', $site->getGUID());
                datalist_set('version', get_version());
 
+               // new installations have run all the upgrades
+               $upgrades = elgg_get_upgrade_files($submissionVars['path'] . 'engine/lib/upgrades/');
+               datalist_set('processed_upgrades', serialize($upgrades));
+
                set_config('view', 'default', $site->getGUID());
                set_config('language', $submissionVars['language'], $site->getGUID());
                set_config('default_access', $submissionVars['siteaccess'], $site->getGUID());
index 0af441b10ae5aa13c515a03931b551c0b0c3297c..6589780b30ec2737bdd4bfae959e4f7eb4efca16 100644 (file)
@@ -17,7 +17,7 @@ define('UPGRADING', 'upgrading');
 require_once(dirname(__FILE__) . "/engine/start.php");
 
 if (get_input('upgrade') == 'upgrade') {
-       if (version_upgrade_check()) {
+       if (elgg_get_unprocessed_upgrades()) {
                version_upgrade();
        }
        elgg_invalidate_simplecache();