Example #1
0
function update_script_selection_form($form, &$form_state)
{
    $count = 0;
    $incompatible_count = 0;
    $form['start'] = array('#tree' => TRUE, '#type' => 'fieldset', '#collapsed' => TRUE, '#collapsible' => TRUE);
    // Ensure system.module's updates appear first.
    $form['start']['system'] = array();
    $updates = update_get_update_list();
    $starting_updates = array();
    $incompatible_updates_exist = FALSE;
    foreach ($updates as $module => $update) {
        if (!isset($update['start'])) {
            $form['start'][$module] = array('#title' => $module, '#item' => $update['warning'], '#prefix' => '<div class="warning">', '#suffix' => '</div>');
            $incompatible_updates_exist = TRUE;
            continue;
        }
        if (!empty($update['pending'])) {
            $starting_updates[$module] = $update['start'];
            $form['start'][$module] = array('#type' => 'hidden', '#value' => $update['start']);
            $form['start'][$module . '_updates'] = array('#theme' => 'item_list', '#items' => $update['pending'], '#title' => $module . ' module');
        }
        if (isset($update['pending'])) {
            $count = $count + count($update['pending']);
        }
    }
    // Find and label any incompatible updates.
    foreach (update_resolve_dependencies($starting_updates) as $function => $data) {
        if (!$data['allowed']) {
            $incompatible_updates_exist = TRUE;
            $incompatible_count++;
            $module_update_key = $data['module'] . '_updates';
            if (isset($form['start'][$module_update_key]['#items'][$data['number']])) {
                $text = $data['missing_dependencies'] ? 'This update will been skipped due to the following missing dependencies: <em>' . implode(', ', $data['missing_dependencies']) . '</em>' : "This update will be skipped due to an error in the module's code.";
                $form['start'][$module_update_key]['#items'][$data['number']] .= '<div class="warning">' . $text . '</div>';
            }
            // Move the module containing this update to the top of the list.
            $form['start'] = array($module_update_key => $form['start'][$module_update_key]) + $form['start'];
        }
    }
    // Warn the user if any updates were incompatible.
    if ($incompatible_updates_exist) {
        drupal_set_message('Some of the pending updates cannot be applied because their dependencies were not met.', 'warning');
    }
    if (empty($count)) {
        drupal_set_message(t('No pending updates.'));
        unset($form);
        $form['links'] = array('#markup' => theme('item_list', array('items' => update_helpful_links())));
    } else {
        $form['help'] = array('#markup' => '<p>The version of Drupal you are updating from has been automatically detected.</p>', '#weight' => -5);
        if ($incompatible_count) {
            $form['start']['#title'] = format_plural($count, '1 pending update (@number_applied to be applied, @number_incompatible skipped)', '@count pending updates (@number_applied to be applied, @number_incompatible skipped)', array('@number_applied' => $count - $incompatible_count, '@number_incompatible' => $incompatible_count));
        } else {
            $form['start']['#title'] = format_plural($count, '1 pending update', '@count pending updates');
        }
        $form['has_js'] = array('#type' => 'hidden', '#default_value' => FALSE);
        $form['actions'] = array('#type' => 'actions');
        $form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Apply pending updates');
    }
    return $form;
}
 /**
  * @return array
  *
  * @see update_script_selection_form()
  */
 private function listUpdates()
 {
     // [
     //   'oxygen' => [
     //   'pending' => [
     //     7001 => 'Update description.',
     //   ],
     //   'start' => 7001,
     // ],
     $list = array();
     require_once DRUPAL_ROOT . '/includes/install.inc';
     drupal_load_updates();
     foreach (update_get_update_list() as $extension => $info) {
         if (!isset($info['start'])) {
             // @todo: The update is incompatible, show a warning?
             continue;
         }
         $list[$extension] = $info['start'];
     }
     $updates = array();
     foreach (update_resolve_dependencies($list) as $update) {
         if (!$update['allowed']) {
             if ($update['missing_dependencies']) {
                 // Some module dependency is missing, so it's not safe to update.
                 continue;
             } else {
                 // There was a PHP syntax error in the module.
                 continue;
             }
         }
         $updates = array($update['module'] => $update['number']) + $updates;
     }
     return $updates;
 }
 function testMissingUpdate()
 {
     $starting_updates = array('update_test_2' => 8001);
     $update_graph = update_resolve_dependencies($starting_updates);
     $this->assertTrue($update_graph['update_test_2_update_8001']['allowed'], "The module's first update function is allowed to run, since it does not have any missing dependencies.");
     $this->assertFalse($update_graph['update_test_2_update_8002']['allowed'], "The module's second update function is not allowed to run, since it has a direct dependency on a missing update.");
     $this->assertFalse($update_graph['update_test_2_update_8003']['allowed'], "The module's third update function is not allowed to run, since it has an indirect dependency on a missing update.");
 }
 /**
  * Test that dependencies between modules are resolved correctly.
  */
 function testUpdateOrderingModuleInterdependency()
 {
     $starting_updates = array('update_test_2' => 8001, 'update_test_3' => 8001);
     $update_order = array_keys(update_resolve_dependencies($starting_updates));
     // Make sure that each dependency is satisfied.
     $first_dependency_satisfied = array_search('update_test_2_update_8001', $update_order) < array_search('update_test_3_update_8001', $update_order);
     $this->assertTrue($first_dependency_satisfied, 'The dependency of the second module on the first module is respected by the update function order.');
     $second_dependency_satisfied = array_search('update_test_3_update_8001', $update_order) < array_search('update_test_2_update_8002', $update_order);
     $this->assertTrue($second_dependency_satisfied, 'The dependency of the first module on the second module is respected by the update function order.');
 }
Example #5
0
 /**
  * Starts the database update batch process.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request object.
  */
 protected function triggerBatch(Request $request)
 {
     $maintenance_mode = $this->state->get('system.maintenance_mode', FALSE);
     // Store the current maintenance mode status in the session so that it can
     // be restored at the end of the batch.
     $_SESSION['maintenance_mode'] = $maintenance_mode;
     // During the update, always put the site into maintenance mode so that
     // in-progress schema changes do not affect visiting users.
     if (empty($maintenance_mode)) {
         $this->state->set('system.maintenance_mode', TRUE);
     }
     $operations = array();
     // Resolve any update dependencies to determine the actual updates that will
     // be run and the order they will be run in.
     $start = $this->getModuleUpdates();
     $updates = update_resolve_dependencies($start);
     // Store the dependencies for each update function in an array which the
     // batch API can pass in to the batch operation each time it is called. (We
     // do not store the entire update dependency array here because it is
     // potentially very large.)
     $dependency_map = array();
     foreach ($updates as $function => $update) {
         $dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : array();
     }
     // Determine updates to be performed.
     foreach ($updates as $function => $update) {
         if ($update['allowed']) {
             // Set the installed version of each module so updates will start at the
             // correct place. (The updates are already sorted, so we can simply base
             // this on the first one we come across in the above foreach loop.)
             if (isset($start[$update['module']])) {
                 drupal_set_installed_schema_version($update['module'], $update['number'] - 1);
                 unset($start[$update['module']]);
             }
             $operations[] = array('update_do_one', array($update['module'], $update['number'], $dependency_map[$function]));
         }
     }
     $post_updates = $this->postUpdateRegistry->getPendingUpdateFunctions();
     if ($post_updates) {
         // Now we rebuild all caches and after that execute the hook_post_update()
         // functions.
         $operations[] = ['drupal_flush_all_caches', []];
         foreach ($post_updates as $function) {
             $operations[] = ['update_invoke_post_update', [$function]];
         }
     }
     $batch['operations'] = $operations;
     $batch += array('title' => $this->t('Updating'), 'init_message' => $this->t('Starting updates'), 'error_message' => $this->t('An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.'), 'finished' => array('\\Drupal\\system\\Controller\\DbUpdateController', 'batchFinished'));
     batch_set($batch);
     // @todo Revisit once https://www.drupal.org/node/2548095 is in.
     return batch_process(Url::fromUri('base://results'), Url::fromUri('base://start'));
 }
Example #6
0
 /**
  * Starts the database update batch process.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request object.
  */
 protected function triggerBatch(Request $request)
 {
     // During the update, bring the site offline so that schema changes do not
     // affect visiting users.
     $maintenance_mode = $this->config('system.maintenance')->get('enabled');
     if (isset($maintenance_mode)) {
         $_SESSION['maintenance_mode'] = $maintenance_mode;
     }
     if (empty($_SESSION['maintenance_mode'])) {
         $this->state->set('system.maintenance_mode', TRUE);
     }
     $operations = array();
     // First of all perform entity definition updates, which will update
     // storage schema if needed, so that module update functions work with
     // the correct entity schema.
     if ($this->entityDefinitionUpdateManager->needsUpdates()) {
         $operations[] = array('update_entity_definitions', array('system', '0 - Update entity definitions'));
     }
     // Resolve any update dependencies to determine the actual updates that will
     // be run and the order they will be run in.
     $start = $this->getModuleUpdates();
     $updates = update_resolve_dependencies($start);
     // Store the dependencies for each update function in an array which the
     // batch API can pass in to the batch operation each time it is called. (We
     // do not store the entire update dependency array here because it is
     // potentially very large.)
     $dependency_map = array();
     foreach ($updates as $function => $update) {
         $dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : array();
     }
     // Determine updates to be performed.
     foreach ($updates as $update) {
         if ($update['allowed']) {
             // Set the installed version of each module so updates will start at the
             // correct place. (The updates are already sorted, so we can simply base
             // this on the first one we come across in the above foreach loop.)
             if (isset($start[$update['module']])) {
                 drupal_set_installed_schema_version($update['module'], $update['number'] - 1);
                 unset($start[$update['module']]);
             }
             // Add this update function to the batch.
             $function = $update['module'] . '_update_' . $update['number'];
             $operations[] = array('update_do_one', array($update['module'], $update['number'], $dependency_map[$function]));
         }
     }
     $batch['operations'] = $operations;
     $batch += array('title' => $this->t('Updating'), 'init_message' => $this->t('Starting updates'), 'error_message' => $this->t('An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.'), 'finished' => array('\\Drupal\\system\\Controller\\DbUpdateController', 'batchFinished'));
     batch_set($batch);
     return batch_process('update.php/results', Url::fromRoute('system.db_update', array('op' => 'start')));
 }
Example #7
0
 /**
  * Starts the database update batch process.
  *
  * @param \Symfony\Component\HttpFoundation\Request $request
  *   The current request object.
  */
 protected function triggerBatch(Request $request)
 {
     $maintenance_mode = $this->state->get('system.maintenance_mode', FALSE);
     // Store the current maintenance mode status in the session so that it can
     // be restored at the end of the batch.
     $_SESSION['maintenance_mode'] = $maintenance_mode;
     // During the update, always put the site into maintenance mode so that
     // in-progress schema changes do not affect visiting users.
     if (empty($maintenance_mode)) {
         $this->state->set('system.maintenance_mode', TRUE);
     }
     $operations = array();
     // Resolve any update dependencies to determine the actual updates that will
     // be run and the order they will be run in.
     $start = $this->getModuleUpdates();
     $updates = update_resolve_dependencies($start);
     // Store the dependencies for each update function in an array which the
     // batch API can pass in to the batch operation each time it is called. (We
     // do not store the entire update dependency array here because it is
     // potentially very large.)
     $dependency_map = array();
     foreach ($updates as $function => $update) {
         $dependency_map[$function] = !empty($update['reverse_paths']) ? array_keys($update['reverse_paths']) : array();
     }
     // Determine updates to be performed.
     foreach ($updates as $function => $update) {
         if ($update['allowed']) {
             // Set the installed version of each module so updates will start at the
             // correct place. (The updates are already sorted, so we can simply base
             // this on the first one we come across in the above foreach loop.)
             if (isset($start[$update['module']])) {
                 drupal_set_installed_schema_version($update['module'], $update['number'] - 1);
                 unset($start[$update['module']]);
             }
             $operations[] = array('update_do_one', array($update['module'], $update['number'], $dependency_map[$function]));
         }
     }
     // Lastly, perform entity definition updates, which will update storage
     // schema if needed. If module update functions need to work with specific
     // entity schema they should call the entity update service for the specific
     // update themselves.
     // @see \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface::applyEntityUpdate()
     // @see \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface::applyFieldUpdate()
     if ($this->entityDefinitionUpdateManager->needsUpdates()) {
         $operations[] = array('update_entity_definitions', array());
     }
     $batch['operations'] = $operations;
     $batch += array('title' => $this->t('Updating'), 'init_message' => $this->t('Starting updates'), 'error_message' => $this->t('An unrecoverable error has occurred. You can find the error message below. It is advised to copy it to the clipboard for reference.'), 'finished' => array('\\Drupal\\system\\Controller\\DbUpdateController', 'batchFinished'));
     batch_set($batch);
     return batch_process(Url::fromUri($request->getUriForPath('/results')), Url::fromUri($request->getUriForPath('/start')));
 }