Issue #2538274 by pwolanin, Wim Leers, dawehner: DbUpdateController has broken mainteneance mode logic, and update.php doesn't run due to aggregated JS assets

8.0.x
Alex Pott 2015-08-05 14:23:11 +01:00
parent 19f73693a9
commit fbde5c4762
5 changed files with 85 additions and 44 deletions

View File

@ -221,7 +221,7 @@ class AssetResolver implements AssetResolverInterface {
// Add the theme name to the cache key since themes may implement
// hook_js_alter(). Additionally add the current language to support
// translation of JavaScript files.
$cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager->getCurrentLanguage()->getId() . ':' . Crypt::hashBase64(serialize($assets));
$cid = 'js:' . $theme_info->getName() . ':' . $this->languageManager->getCurrentLanguage()->getId() . ':' . Crypt::hashBase64(serialize($assets)) . (int) $optimize;
if ($cached = $this->cache->get($cid)) {
list($js_assets_header, $js_assets_footer, $settings, $settings_in_header) = $cached->data;

View File

@ -164,7 +164,7 @@ class HtmlResponseAttachmentsProcessor implements AttachmentsResponseProcessorIn
// Print scripts - if any are present.
if (isset($placeholders['scripts']) || isset($placeholders['scripts_bottom'])) {
// Optimize JS if necessary, but only during normal site operation.
$optimize_js = !defined('MAINTENANCE_MODE') && $this->config->get('js.preprocess');
$optimize_js = !defined('MAINTENANCE_MODE') && !\Drupal::state()->get('system.maintenance_mode') && $this->config->get('js.preprocess');
list($js_assets_header, $js_assets_footer) = $this->assetResolver->getJsAssets($assets, $optimize_js);
$variables['scripts'] = $this->jsCollectionRenderer->render($js_assets_header);
$variables['scripts_bottom'] = $this->jsCollectionRenderer->render($js_assets_footer);

View File

@ -544,13 +544,13 @@ class DbUpdateController extends ControllerBase {
* 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'])) {
$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);
}
@ -630,11 +630,11 @@ class DbUpdateController extends ControllerBase {
$_SESSION['updates_remaining'] = $operations;
// Now that the update is done, we can put the site back online if it was
// previously in maintenance mode.
if (isset($_SESSION['maintenance_mode'])) {
// previously not in maintenance mode.
if (empty($_SESSION['maintenance_mode'])) {
\Drupal::state()->set('system.maintenance_mode', FALSE);
unset($_SESSION['maintenance_mode']);
}
unset($_SESSION['maintenance_mode']);
}
/**

View File

@ -7,6 +7,7 @@
namespace Drupal\system\Tests\System;
use Drupal\Core\Url;
use Drupal\simpletest\WebTestBase;
/**
@ -30,6 +31,7 @@ class SiteMaintenanceTest extends WebTestBase {
// Configure 'node' as front page.
$this->config('system.site')->set('page.front', '/node')->save();
$this->config('system.performance')->set('js.preprocess', 1)->save();
// Create a user allowed to access site in maintenance mode.
$this->user = $this->drupalCreateUser(array('access site in maintenance mode'));
@ -42,6 +44,10 @@ class SiteMaintenanceTest extends WebTestBase {
* Verify site maintenance mode functionality.
*/
protected function testSiteMaintenance() {
$this->drupalGet(Url::fromRoute('user.page'));
// JS should be aggregated, so drupal.js is not in the page source.
$links = $this->xpath('//script[contains(@src, :href)]', array(':href' => '/core/misc/drupal.js'));
$this->assertFalse(isset($links[0]), 'script /core/misc/drupal.js not in page');
// Turn on maintenance mode.
$edit = array(
'maintenance_mode' => 1,
@ -52,7 +58,10 @@ class SiteMaintenanceTest extends WebTestBase {
$user_message = t('Operating in maintenance mode.');
$offline_message = t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => $this->config('system.site')->get('name')));
$this->drupalGet('');
$this->drupalGet(Url::fromRoute('user.page'));
// JS should not be aggregated, so drupal.js is expected in the page source.
$links = $this->xpath('//script[contains(@src, :href)]', array(':href' => '/core/misc/drupal.js'));
$this->assertTrue(isset($links[0]), 'script /core/misc/drupal.js in page');
$this->assertRaw($admin_message, 'Found the site maintenance mode message.');
// Logout and verify that offline message is displayed.

View File

@ -173,37 +173,11 @@ class UpdateScriptTest extends WebTestBase {
* Tests update.php after performing a successful update.
*/
function testSuccessfulUpdateFunctionality() {
$schema_version = drupal_get_installed_schema_version('update_script_test');
$this->assertEqual($schema_version, 8001, 'update_script_test is initially installed with schema version 8001.');
// Set the installed schema version to one less than the current update.
drupal_set_installed_schema_version('update_script_test', $schema_version - 1);
$schema_version = drupal_get_installed_schema_version('update_script_test', TRUE);
$this->assertEqual($schema_version, 8000, 'update_script_test schema version overridden to 8000.');
// Click through update.php with 'administer software updates' permission.
$this->drupalLogin($this->updateUser);
$this->drupalGet($this->updateUrl, array('external' => TRUE));
$this->clickLink(t('Continue'));
$this->clickLink(t('Apply pending updates'));
// Verify that updates were completed successfully.
$this->assertText('Updates were attempted.');
$this->assertLink('site');
$this->assertText('The update_script_test_update_8001() update was executed successfully.');
// Verify that no 7.x updates were run.
$this->assertNoText('The update_script_test_update_7200() update was executed successfully.');
$this->assertNoText('The update_script_test_update_7201() update was executed successfully.');
// Verify that there are no links to different parts of the workflow.
$this->assertNoLink('Administration pages');
$this->assertNoLinkByHref('update.php', 0);
$this->assertNoLink('logged');
// Verify the front page can be visited following the upgrade.
$this->clickLink('Front page');
$this->assertResponse(200);
$initial_maintenance_mode = $this->container->get('state')->get('system.maintenance_mode');
$this->assertFalse($initial_maintenance_mode, 'Site is not in maintenance mode.');
$this->updateScriptTest($initial_maintenance_mode);
$final_maintenance_mode = $this->container->get('state')->get('system.maintenance_mode');
$this->assertEqual($final_maintenance_mode, $initial_maintenance_mode, 'Maintenance mode should not have changed after database updates.');
// Reset the static cache to ensure we have the most current setting.
$schema_version = drupal_get_installed_schema_version('update_script_test', TRUE);
@ -229,6 +203,64 @@ class UpdateScriptTest extends WebTestBase {
$this->assertResponse(200);
}
/**
* Tests update.php while in maintenance mode.
*/
function testMaintenanceModeUpdateFunctionality() {
$this->container->get('state')
->set('system.maintenance_mode', TRUE);
$initial_maintenance_mode = $this->container->get('state')
->get('system.maintenance_mode');
$this->assertTrue($initial_maintenance_mode, 'Site is in maintenance mode.');
$this->updateScriptTest($initial_maintenance_mode);
$final_maintenance_mode = $this->container->get('state')
->get('system.maintenance_mode');
$this->assertEqual($final_maintenance_mode, $initial_maintenance_mode, 'Maintenance mode should not have changed after database updates.');
}
/**
* Helper function to run updates via the browser.
*/
protected function updateScriptTest($maintenance_mode) {
$schema_version = drupal_get_installed_schema_version('update_script_test');
$this->assertEqual($schema_version, 8001, 'update_script_test is initially installed with schema version 8001.');
// Set the installed schema version to one less than the current update.
drupal_set_installed_schema_version('update_script_test', $schema_version - 1);
$schema_version = drupal_get_installed_schema_version('update_script_test', TRUE);
$this->assertEqual($schema_version, 8000, 'update_script_test schema version overridden to 8000.');
// Click through update.php with 'administer software updates' permission.
$this->drupalLogin($this->updateUser);
if ($maintenance_mode) {
$this->assertText('Operating in maintenance mode.');
}
else {
$this->assertNoText('Operating in maintenance mode.');
}
$this->drupalGet($this->updateUrl, array('external' => TRUE));
$this->clickLink(t('Continue'));
$this->clickLink(t('Apply pending updates'));
// Verify that updates were completed successfully.
$this->assertText('Updates were attempted.');
$this->assertLink('site');
$this->assertText('The update_script_test_update_8001() update was executed successfully.');
// Verify that no 7.x updates were run.
$this->assertNoText('The update_script_test_update_7200() update was executed successfully.');
$this->assertNoText('The update_script_test_update_7201() update was executed successfully.');
// Verify that there are no links to different parts of the workflow.
$this->assertNoLink('Administration pages');
$this->assertNoLinkByHref('update.php', 0);
$this->assertNoLink('logged');
// Verify the front page can be visited following the upgrade.
$this->clickLink('Front page');
$this->assertResponse(200);
}
/**
* Returns the Drupal 7 system table schema.
*/