forked from a64f7bb4-7358-4778-9fbe-3b882c34cc1d/v1
180 lines
6.7 KiB
PHP
180 lines
6.7 KiB
PHP
<?php
|
|
|
|
namespace Drupal\Tests;
|
|
|
|
use Drupal\Core\Database\Database;
|
|
use Drupal\Core\Url;
|
|
|
|
/**
|
|
* Trait UpdatePathTestTrait.
|
|
*
|
|
* For use on \Drupal\Tests\BrowserTestBase tests.
|
|
*/
|
|
trait UpdatePathTestTrait {
|
|
use RequirementsPageTrait;
|
|
use SchemaCheckTestTrait;
|
|
|
|
/**
|
|
* Fail the test if there are failed updates.
|
|
*
|
|
* @var bool
|
|
*/
|
|
protected $checkFailedUpdates = TRUE;
|
|
|
|
/**
|
|
* Helper function to run pending database updates.
|
|
*
|
|
* @param string|null $update_url
|
|
* The update URL.
|
|
*/
|
|
protected function runUpdates($update_url = NULL) {
|
|
if (!$update_url) {
|
|
$update_url = Url::fromRoute('system.db_update');
|
|
}
|
|
require_once $this->root . '/core/includes/update.inc';
|
|
// The site might be broken at the time so logging in using the UI might
|
|
// not work, so we use the API itself.
|
|
$this->writeSettings([
|
|
'settings' => [
|
|
'update_free_access' => (object) [
|
|
'value' => TRUE,
|
|
'required' => TRUE,
|
|
],
|
|
],
|
|
]);
|
|
|
|
$this->drupalGet($update_url);
|
|
$this->updateRequirementsProblem();
|
|
$this->clickLink('Continue');
|
|
|
|
$this->doSelectionTest();
|
|
// Run the update hooks.
|
|
$this->clickLink('Apply pending updates');
|
|
$this->checkForMetaRefresh();
|
|
|
|
// Ensure there are no failed updates.
|
|
if ($this->checkFailedUpdates) {
|
|
$failure = $this->cssSelect('.failure');
|
|
if ($failure) {
|
|
$this->fail('The update failed with the following message: "' . reset($failure)->getText() . '"');
|
|
}
|
|
|
|
// Ensure that there are no pending updates.
|
|
foreach (['update', 'post_update'] as $update_type) {
|
|
switch ($update_type) {
|
|
case 'update':
|
|
drupal_load_updates();
|
|
$all_updates = update_get_update_list();
|
|
break;
|
|
|
|
case 'post_update':
|
|
$all_updates = \Drupal::service('update.post_update_registry')->getPendingUpdateInformation();
|
|
break;
|
|
}
|
|
foreach ($all_updates as $module => $updates) {
|
|
if (!empty($updates['pending'])) {
|
|
foreach (array_keys($updates['pending']) as $update_name) {
|
|
$this->fail("The $update_name() update function from the $module module did not run.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Ensure that the container is updated if any modules are installed or
|
|
// uninstalled during the update.
|
|
/** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
|
|
$module_handler = $this->container->get('module_handler');
|
|
$config_module_list = $this->config('core.extension')->get('module');
|
|
$module_handler_list = $module_handler->getModuleList();
|
|
$modules_installed = FALSE;
|
|
// Modules that are in configuration but not the module handler have been
|
|
// installed.
|
|
/** @var \Drupal\Core\Extension\ModuleExtensionList $module_list */
|
|
$module_list = $this->container->get('extension.list.module');
|
|
foreach (array_keys(array_diff_key($config_module_list, $module_handler_list)) as $module) {
|
|
$module_handler->addModule($module, $module_list->getPath($module));
|
|
$modules_installed = TRUE;
|
|
}
|
|
$modules_uninstalled = FALSE;
|
|
$module_handler_list = $module_handler->getModuleList();
|
|
// Modules that are in the module handler but not configuration have been
|
|
// uninstalled.
|
|
foreach (array_keys(array_diff_key($module_handler_list, $config_module_list)) as $module) {
|
|
$modules_uninstalled = TRUE;
|
|
unset($module_handler_list[$module]);
|
|
}
|
|
if ($modules_installed || $modules_uninstalled) {
|
|
// Note that resetAll() does not reset the kernel module list so we
|
|
// have to do that manually.
|
|
$this->kernel->updateModules($module_handler_list, $module_handler_list);
|
|
}
|
|
|
|
// Close any open database connections. This allows DB drivers that store
|
|
// static information to refresh it in the update runner.
|
|
// @todo https://drupal.org/i/3222121 consider doing this in
|
|
// \Drupal\Core\DrupalKernel::initializeContainer() for container
|
|
// rebuilds.
|
|
foreach (Database::getAllConnectionInfo() as $key => $info) {
|
|
Database::closeConnection(NULL, $key);
|
|
}
|
|
|
|
// If we have successfully clicked 'Apply pending updates' then we need to
|
|
// clear the caches in the update test runner as this has occurred as part
|
|
// of the updates.
|
|
$this->resetAll();
|
|
|
|
// The config schema can be incorrect while the update functions are being
|
|
// executed. But once the update has been completed, it needs to be valid
|
|
// again. Assert the schema of all configuration objects now.
|
|
$names = $this->container->get('config.storage')->listAll();
|
|
|
|
// Allow tests to opt out of checking specific configuration.
|
|
$exclude = $this->getConfigSchemaExclusions();
|
|
/** @var \Drupal\Core\Config\TypedConfigManagerInterface $typed_config */
|
|
$typed_config = $this->container->get('config.typed');
|
|
foreach ($names as $name) {
|
|
if (in_array($name, $exclude, TRUE)) {
|
|
// Skip checking schema if the config is listed in the
|
|
// $configSchemaCheckerExclusions property.
|
|
continue;
|
|
}
|
|
$config = $this->config($name);
|
|
$this->assertConfigSchema($typed_config, $name, $config->get());
|
|
}
|
|
|
|
// Ensure that the update hooks updated all entity schema.
|
|
$needs_updates = \Drupal::entityDefinitionUpdateManager()->needsUpdates();
|
|
if ($needs_updates) {
|
|
foreach (\Drupal::entityDefinitionUpdateManager()->getChangeSummary() as $entity_type_id => $summary) {
|
|
$entity_type_label = \Drupal::entityTypeManager()->getDefinition($entity_type_id)->getLabel();
|
|
foreach ($summary as $message) {
|
|
$this->fail("$entity_type_label: $message");
|
|
}
|
|
}
|
|
// The above calls to `fail()` should prevent this from ever being
|
|
// called, but it is here in case something goes really wrong.
|
|
$this->assertFalse($needs_updates, 'After all updates ran, entity schema is up to date.');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tests the selection page.
|
|
*/
|
|
protected function doSelectionTest() {
|
|
// No-op. Tests wishing to do test the selection page or the general
|
|
// update.php environment before running update.php can override this method
|
|
// and implement their required tests.
|
|
}
|
|
|
|
/**
|
|
* Installs the update_script_test module and makes an update available.
|
|
*/
|
|
protected function ensureUpdatesToRun() {
|
|
\Drupal::service('module_installer')->install(['update_script_test']);
|
|
// Reset the schema so there is an update to run.
|
|
\Drupal::service('update.update_hook_registry')->setInstalledVersion('update_script_test', 8000);
|
|
}
|
|
|
|
}
|