=== modified file 'includes/update.inc' --- includes/update.inc 2009-08-22 18:24:14 +0000 +++ includes/update.inc 2009-08-23 01:54:39 +0000 @@ -273,7 +273,7 @@ function update_fix_d7_requirements() { * * Install profiles are now treated as modules by Drupal, and have an upgrade path * based on their schema version in the system table. - * + * * The install profile will be set to schema_version 0, as it has already been * installed. Any other hook_update_N functions provided by the install profile * will be run by update.php. @@ -365,13 +365,28 @@ function update_parse_db_url($db_url) { * Perform one update and store the results which will later be displayed on * the finished page. * - * An update function can force the current and all later updates for this - * module to abort by returning a $ret array with an element like: - * $ret['#abort'] = array('success' => FALSE, 'query' => 'What went wrong'); - * The schema version will not be updated in this case, and all the - * aborted updates will continue to appear on update.php as updates that + * If an update function completes successfully, it should return a message + * as a string indicating success, for example: + * @code + * return t('New index added successfully.'); + * @endcode + * + * If it fails for whatever reason, it should throw an instance of + * DrupalUpdateException with an appropriate error message, for example: + * @code + * throw new DrupalUpdateException(t('Description of what went wrong')); + * @endcode + * + * If an exception is thrown, the current and all later updates for this module + * will be aborded. The schema version will not be updated in this case, and all + * the aborted updates will continue to appear on update.php as updates that * have not yet been run. * + * If an update function needs to be re-run as part of a batch process, it + * should accept the $context array by reference as its first parameter + * and set the #finished property to the percentage completed that it is, as a + * decmial fraction of 1. + * * @param $module * The module whose update will be run. * @param $number @@ -386,9 +401,44 @@ function update_do_one($module, $number, return; } + if (!isset($context['log'])) { + $context['log'] = (bool) variable_get('update_log_queries', FALSE); + } + + $ret = array(); $function = $module . '_update_' . $number; if (function_exists($function)) { - $ret = $function($context['sandbox']); + try { + if ($context['log']) { + Database::startLog($function); + } + $ret = array( + 'results' => array( + 'success' => TRUE, + 'query' => $function($context['sandbox']), + ), + ); + + // @TODO Remove this block after all updates have been converted to + // return only strings. + if (is_array($ret['results']['query'])) { + $ret = $ret['results']['query']; + } + } + // @TODO We may want to do different error handling for different exception + // types, but for now we'll just print the message. + catch (DrupalUpdateException $e) { + $ret['results'] = array('success' => FALSE, 'query' => $e->getMessage()); + $ret['#abort'] = TRUE; + } + catch (Exception $e) { + $ret['results'] = array('success' => FALSE, 'query' => $e->getMessage()); + $ret['#abort'] = TRUE; + } + + if ($context['log']) { + $ret['queries'] = Database::getLog($function); + } } if (isset($ret['#finished'])) { @@ -416,6 +466,11 @@ function update_do_one($module, $number, } /** + * @class Exception class used to throw error if a module update fails. + */ +class DrupalUpdateException extends Exception { } + +/** * Start the database update batch process. * * @param $start @@ -516,7 +571,7 @@ function update_finished($success, $resu function update_get_update_list() { // Make sure that the system module is first in the list of updates. $ret = array('system' => array()); - + $modules = drupal_get_installed_schema_version(NULL, FALSE, TRUE); foreach ($modules as $module => $schema_version) { $pending = array(); @@ -530,7 +585,7 @@ function update_get_update_list() { $ret[$module]['warning'] = '' . $module . ' module can not be updated. Its schema version is ' . $schema_version . '. Updates up to and including ' . $last_removed . ' have been removed in this release. In order to update ' . $module . ' module, you will first need to upgrade to the last version in which these updates were available.'; continue; } - + $updates = drupal_map_assoc($updates); foreach (array_keys($updates) as $update) { if ($update > $schema_version) { @@ -548,7 +603,7 @@ function update_get_update_list() { } } } - + if (empty($ret['system'])) { unset($ret['system']); } === modified file 'modules/system/system.install' --- modules/system/system.install 2009-08-22 18:24:14 +0000 +++ modules/system/system.install 2009-08-23 01:56:26 +0000 @@ -44,7 +44,7 @@ function system_requirements($phase) { 'severity' => REQUIREMENT_INFO, 'weight' => -9 ); - } + } } // Web server information. @@ -2455,7 +2455,66 @@ function system_update_7036() { return $ret; } + +/** + * Test update 1. This should succeed and use the legacy return format. + * + * DO NOT COMMIT THIS FUNCTION. + */ +function system_update_9001() { + + $ret[] = array('success' => TRUE, 'query' => t('This is the return message.')); + return $ret; +} + /** - * @} End of "defgroup updates-6.x-to-7.x" - * The next series of updates should start at 8000. + * Test update 2. This should succeed. + * + * DO NOT COMMIT THIS FUNCTION. */ +function system_update_9002() { + + // Do something interesting here. + return t('Yay, it worked'); +} + +/** + * Test update 3. This makes sure batching works. + * + * DO NOT COMMIT THIS FUNCITON. + */ +function system_update_9003(&$sandbox) { + + if (empty($sandbox['step'])) { + $sandbox['step'] = 1; + } + + if ($sandbox['step'] == 1) { + $sandbox['step'] = 2; + $sandbox['#finished'] = 0.5; + } + + return t('Finished running when step is: ' . $sandbox['step']); +} + +/** + * Test update 4. This should fail. + * + * DO NOT COMMIT THIS FUNCTION. + */ +function system_update_9004() { + + throw new DrupalUpdateException(t('This is an error message.')); + + return t('You should not see this message.'); +} + +/** + * Test update 5. This shouldn't even run. + * + * DO NOT COMMIT THIS FUNCTION. + */ +function system_update_9005() { + return t('You should not see this message, either.'); +} +