update.inc

  1. 8.0.x commands/core/drupal/update.inc
  2. 6.x commands/core/drupal/update.inc
  3. 7.x commands/core/drupal/update.inc
  4. 4.x commands/core/drupal/update.inc
  5. 5.x commands/core/drupal/update.inc
  6. master commands/core/drupal/update.inc

Update.php for provisioned sites. This file is a derivative of the standard drupal update.php, which has been modified to allow being run from the command line.

Functions

Namesort descending Description
drush_get_update_list
drush_update_batch Start the database update batch process.
drush_update_do_one Perform one update and store the results which will later be displayed on the finished page.
drush_update_finished
updatedb_status Return a 2 item array with
update_main
_update_batch_command

File

commands/core/drupal/update.inc
View source
  1. <?php
  2. /**
  3. * @file
  4. * Update.php for provisioned sites.
  5. * This file is a derivative of the standard drupal update.php,
  6. * which has been modified to allow being run from the command
  7. * line.
  8. */
  9. use Drush\Log\LogLevel;
  10. /**
  11. * Drupal's update.inc has functions that are in previous update_X.inc files
  12. * for example, update_check_incompatibility() which can prove useful when
  13. * enabling modules.
  14. */
  15. require_once DRUSH_DRUPAL_CORE . '/includes/update.inc';
  16. /**
  17. * Perform one update and store the results which will later be displayed on
  18. * the finished page.
  19. *
  20. * An update function can force the current and all later updates for this
  21. * module to abort by returning a $ret array with an element like:
  22. * $ret['#abort'] = array('success' => FALSE, 'query' => 'What went wrong');
  23. * The schema version will not be updated in this case, and all the
  24. * aborted updates will continue to appear on update.php as updates that
  25. * have not yet been run.
  26. *
  27. * @param $module
  28. * The module whose update will be run.
  29. * @param $number
  30. * The update number to run.
  31. * @param $context
  32. * The batch context array
  33. */
  34. function drush_update_do_one($module, $number, $dependency_map, &$context) {
  35. $function = $module . '_update_' . $number;
  36. // If this update was aborted in a previous step, or has a dependency that
  37. // was aborted in a previous step, go no further.
  38. if (!empty($context['results']['#abort']) && array_intersect($context['results']['#abort'], array_merge($dependency_map, array($function)))) {
  39. return;
  40. }
  41. $context['log'] = FALSE;
  42. $ret = array();
  43. if (function_exists($function)) {
  44. try {
  45. if ($context['log']) {
  46. Database::startLog($function);
  47. }
  48. drush_log("Executing " . $function);
  49. $ret['results']['query'] = $function($context['sandbox']);
  50. $ret['results']['success'] = TRUE;
  51. }
  52. // @TODO We may want to do different error handling for different exception
  53. // types, but for now we'll just print the message.
  54. catch (Exception $e) {
  55. $ret['#abort'] = array('success' => FALSE, 'query' => $e->getMessage());
  56. drush_set_error('DRUPAL_EXCEPTION', $e->getMessage());
  57. }
  58. if ($context['log']) {
  59. $ret['queries'] = Database::getLog($function);
  60. }
  61. }
  62. if (isset($context['sandbox']['#finished'])) {
  63. $context['finished'] = $context['sandbox']['#finished'];
  64. unset($context['sandbox']['#finished']);
  65. }
  66. if (!isset($context['results'][$module])) {
  67. $context['results'][$module] = array();
  68. }
  69. if (!isset($context['results'][$module][$number])) {
  70. $context['results'][$module][$number] = array();
  71. }
  72. $context['results'][$module][$number] = array_merge($context['results'][$module][$number], $ret);
  73. if (!empty($ret['#abort'])) {
  74. // Record this function in the list of updates that were aborted.
  75. $context['results']['#abort'][] = $function;
  76. }
  77. // Record the schema update if it was completed successfully.
  78. if ($context['finished'] == 1 && empty($ret['#abort'])) {
  79. drupal_set_installed_schema_version($module, $number);
  80. }
  81. $context['message'] = 'Performing ' . $function;
  82. }
  83. function update_main() {
  84. // In D8, we expect to be in full bootstrap.
  85. drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_FULL);
  86. require_once DRUPAL_ROOT . '/core/includes/install.inc';
  87. require_once DRUPAL_ROOT . '/core/includes/update.inc';
  88. drupal_load_updates();
  89. update_fix_compatibility();
  90. $pending = update_get_update_list();
  91. $start = array();
  92. $change_summary = \Drupal::service('entity.definition_update_manager')->getChangeSummary();
  93. // Print a list of pending updates for this module and get confirmation.
  94. if (count($pending) || count($change_summary)) {
  95. drush_print(dt('The following updates are pending:'));
  96. drush_print();
  97. foreach ($change_summary as $entity_type_id => $changes) {
  98. drush_print($entity_type_id . ' entity type : ');
  99. foreach ($changes as $change) {
  100. drush_print(strip_tags($change), 2);
  101. }
  102. }
  103. foreach ($pending as $module => $updates) {
  104. if (isset($updates['start'])) {
  105. drush_print($module . ' module : ');
  106. if (isset($updates['start'])) {
  107. $start[$module] = $updates['start'];
  108. foreach ($updates['pending'] as $update) {
  109. drush_print(strip_tags($update), 2);
  110. }
  111. }
  112. drush_print();
  113. }
  114. }
  115. if (!drush_confirm(dt('Do you wish to run all pending updates?'))) {
  116. return drush_user_abort();
  117. }
  118. drush_update_batch($start);
  119. }
  120. else {
  121. drush_log(dt("No database updates required"), LogLevel::SUCCESS);
  122. }
  123. }
  124. function _update_batch_command($id) {
  125. // In D8, we expect to be in full bootstrap.
  126. drush_bootstrap_to_phase(DRUSH_BOOTSTRAP_DRUPAL_FULL);
  127. drush_batch_command($id);
  128. }
  129. /**
  130. * Start the database update batch process.
  131. *
  132. * @param $start
  133. * An array of all the modules and which update to start at.
  134. * @param $redirect
  135. * Path to redirect to when the batch has finished processing.
  136. * @param $url
  137. * URL of the batch processing page (should only be used for separate
  138. * scripts like update.php).
  139. * @param $batch
  140. * Optional parameters to pass into the batch API.
  141. * @param $redirect_callback
  142. * (optional) Specify a function to be called to redirect to the progressive
  143. * processing page.
  144. */
  145. function drush_update_batch($start) {
  146. $start = drush_get_update_list();
  147. // Resolve any update dependencies to determine the actual updates that will
  148. // be run and the order they will be run in.
  149. $updates = update_resolve_dependencies($start);
  150. // Store the dependencies for each update function in an array which the
  151. // batch API can pass in to the batch operation each time it is called. (We
  152. // do not store the entire update dependency array here because it is
  153. // potentially very large.)
  154. $dependency_map = array();
  155. foreach ($updates as $function => $update) {
  156. $dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : array();
  157. }
  158. $operations = array();
  159. // First of all perform entity definition updates, which will update
  160. // storage schema if needed, so that module update functions work with
  161. // the correct entity schema.
  162. if (\Drupal::service('entity.definition_update_manager')->needsUpdates()) {
  163. $operations[] = array('update_entity_definitions', array('system', '0 - Update entity definitions'));
  164. }
  165. foreach ($updates as $update) {
  166. if ($update['allowed']) {
  167. // Set the installed version of each module so updates will start at the
  168. // correct place. (The updates are already sorted, so we can simply base
  169. // this on the first one we come across in the above foreach loop.)
  170. if (isset($start[$update['module']])) {
  171. drupal_set_installed_schema_version($update['module'], $update['number'] - 1);
  172. unset($start[$update['module']]);
  173. }
  174. // Add this update function to the batch.
  175. $function = $update['module'] . '_update_' . $update['number'];
  176. $operations[] = array('drush_update_do_one', array($update['module'], $update['number'], $dependency_map[$function]));
  177. }
  178. }
  179. $batch['operations'] = $operations;
  180. $batch += array(
  181. 'title' => 'Updating',
  182. 'init_message' => 'Starting updates',
  183. 'error_message' => 'An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.',
  184. // 'finished' => array('finished' => array('\Drupal\system\Controller\DbUpdateController', 'batchFinished')),
  185. 'file' => 'includes/update.inc',
  186. );
  187. batch_set($batch);
  188. \Drupal::service('state')->set('system.maintenance_mode', TRUE);
  189. drush_backend_batch_process('updatedb-batch-process');
  190. \Drupal::service('state')->set('system.maintenance_mode', FALSE);
  191. }
  192. // Copy of protected \Drupal\system\Controller\DbUpdateController::getModuleUpdates.
  193. function drush_get_update_list() {
  194. $return = array();
  195. $updates = update_get_update_list();
  196. foreach ($updates as $module => $update) {
  197. $return[$module] = $update['start'];
  198. }
  199. return $return;
  200. }
  201. function drush_update_finished($success, $results, $operations) {
  202. // Nothing to do here. All caches already cleared. Kept as documentation of 'finished' callback.
  203. }
  204. /**
  205. * Return a 2 item array with
  206. * - an array where each item is a 3 item associative array describing a pending update.
  207. * - an array listing the first update to run, keyed by module.
  208. */
  209. function updatedb_status() {
  210. $pending = update_get_update_list();
  211. $return = array();
  212. // Ensure system module's updates run first.
  213. $start['system'] = array();
  214. foreach (\Drupal::service('entity.definition_update_manager')->getChangeSummary() as $entity_type_id => $changes) {
  215. foreach ($changes as $change) {
  216. $return[] = array(
  217. 'module' => dt('@type entity type', array('@type' => $entity_type_id)), 'update_id' => '', 'description' => strip_tags($change));
  218. }
  219. }
  220. // Print a list of pending updates for this module and get confirmation.
  221. foreach ($pending as $module => $updates) {
  222. if (isset($updates['start'])) {
  223. foreach ($updates['pending'] as $update_id => $description) {
  224. // Strip cruft from front.
  225. $description = str_replace($update_id . ' - ', '', $description);
  226. $return[] = array('module' => ucfirst($module), 'update_id' => $update_id, 'description' => $description);
  227. }
  228. if (isset($updates['start'])) {
  229. $start[$module] = $updates['start'];
  230. }
  231. }
  232. }
  233. return array($return, $start);
  234. }