Issue #1394648 by David_Rothstein: Fixed The installer's cache backend no longer overrides all cache-clearing methods, which can lead to fatal errors.
parent
b08c8b478e
commit
abb86f9828
|
@ -34,26 +34,26 @@ use Exception;
|
|||
class InstallBackend extends DatabaseBackend {
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\CacheBackendInterface::get().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::get().
|
||||
*/
|
||||
function get($cid) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\CacheBackendInterface::getMultiple().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::getMultiple().
|
||||
*/
|
||||
function getMultiple(&$cids) {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\CacheBackendInterface::set().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::set().
|
||||
*/
|
||||
function set($cid, $data, $expire = CACHE_PERMANENT, array $tags = array()) {}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Cache\CacheBackendInterface::delete().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::delete().
|
||||
*/
|
||||
function delete($cid) {
|
||||
try {
|
||||
|
@ -65,7 +65,7 @@ class InstallBackend extends DatabaseBackend {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Cache\CacheBackendInterface::deleteMultiple().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::deleteMultiple().
|
||||
*/
|
||||
function deleteMultiple(array $cids) {
|
||||
try {
|
||||
|
@ -77,7 +77,7 @@ class InstallBackend extends DatabaseBackend {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Cache\CacheBackendInterface::deletePrefix().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::deletePrefix().
|
||||
*/
|
||||
function deletePrefix($prefix) {
|
||||
try {
|
||||
|
@ -88,6 +88,9 @@ class InstallBackend extends DatabaseBackend {
|
|||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::invalidateTags().
|
||||
*/
|
||||
function invalidateTags(array $tags) {
|
||||
try {
|
||||
if (class_exists('Drupal\Core\Database\Database')) {
|
||||
|
@ -98,7 +101,7 @@ class InstallBackend extends DatabaseBackend {
|
|||
}
|
||||
|
||||
/**
|
||||
* Implements Drupal\Core\Cache\CacheBackendInterface::flush().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::flush().
|
||||
*/
|
||||
function flush() {
|
||||
try {
|
||||
|
@ -110,9 +113,39 @@ class InstallBackend extends DatabaseBackend {
|
|||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\CacheBackendInterface::isEmpty().
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::expire().
|
||||
*/
|
||||
function expire() {
|
||||
try {
|
||||
if (class_exists('Drupal\Core\Database\Database')) {
|
||||
parent::expire();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::garbageCollection().
|
||||
*/
|
||||
function garbageCollection() {
|
||||
try {
|
||||
if (class_exists('Drupal\Core\Database\Database')) {
|
||||
parent::garbageCollection();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides Drupal\Core\Cache\DatabaseBackend::isEmpty().
|
||||
*/
|
||||
function isEmpty() {
|
||||
try {
|
||||
if (class_exists('Drupal\Core\Database\Database')) {
|
||||
return parent::isEmpty();
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Drupal\Core\Cache\DatabaseBackend;
|
||||
use Drupal\Core\Cache\InstallBackend;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
class CacheTestCase extends WebTestBase {
|
||||
|
@ -457,3 +459,144 @@ class CacheIsEmptyCase extends CacheTestCase {
|
|||
$this->assertTrue($cache->isEmpty(), t('The cache bin is empty'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the cache backend used for installing Drupal.
|
||||
*/
|
||||
class CacheInstallTestCase extends CacheTestCase {
|
||||
protected $profile = 'testing';
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Cache install test',
|
||||
'description' => 'Confirm that the cache backend used for installing Drupal works correctly.',
|
||||
'group' => 'Cache',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('cache_test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the cache backend used for installing Drupal.
|
||||
*
|
||||
* While Drupal is being installed, the cache system must deal with the fact
|
||||
* that the database is not initially available, and, after it is available,
|
||||
* the fact that other requests that take place while Drupal is being
|
||||
* installed (for example, Ajax requests triggered via the installer's user
|
||||
* interface) may cache data in the database, which needs to be cleared when
|
||||
* the installer makes changes that would result in it becoming stale.
|
||||
*
|
||||
* We cannot test this process directly, so instead we test it by switching
|
||||
* between the normal database cache (Drupal\Core\Cache\DatabaseBackend) and
|
||||
* the installer cache (Drupal\Core\Cache\InstallBackend) while setting and
|
||||
* clearing various items in the cache.
|
||||
*/
|
||||
function testCacheInstall() {
|
||||
$database_cache = new DatabaseBackend('test');
|
||||
$install_cache = new InstallBackend('test');
|
||||
|
||||
// Store an item in the database cache, and confirm that the installer's
|
||||
// cache backend recognizes that the cache is not empty.
|
||||
$database_cache->set('cache_one', 'One');
|
||||
$this->assertFalse($install_cache->isEmpty());
|
||||
$database_cache->delete('cache_one');
|
||||
$this->assertTrue($install_cache->isEmpty());
|
||||
|
||||
// Store an item in the database cache, then use the installer's cache
|
||||
// backend to delete it. Afterwards, confirm that it is no longer in the
|
||||
// database cache.
|
||||
$database_cache->set('cache_one', 'One');
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$install_cache->delete('cache_one');
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
|
||||
// Store multiple items in the database cache, then use the installer's
|
||||
// cache backend to delete them. Afterwards, confirm that they are no
|
||||
// longer in the database cache.
|
||||
$database_cache->set('cache_one', 'One');
|
||||
$database_cache->set('cache_two', 'Two');
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$this->assertEqual($database_cache->get('cache_two')->data, 'Two');
|
||||
$install_cache->deleteMultiple(array('cache_one', 'cache_two'));
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
$this->assertFalse($database_cache->get('cache_two'));
|
||||
|
||||
// Store multiple items in the database cache, then use the installer's
|
||||
// cache backend to delete them via a wildcard prefix. Afterwards, confirm
|
||||
// that they are no longer in the database cache.
|
||||
$database_cache->set('cache_one', 'One');
|
||||
$database_cache->set('cache_two', 'Two');
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$this->assertEqual($database_cache->get('cache_two')->data, 'Two');
|
||||
$install_cache->deletePrefix('cache_');
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
$this->assertFalse($database_cache->get('cache_two'));
|
||||
|
||||
// Store multiple items in the database cache, then use the installer's
|
||||
// cache backend to flush the cache. Afterwards, confirm that they are no
|
||||
// longer in the database cache.
|
||||
$database_cache->set('cache_one', 'One');
|
||||
$database_cache->set('cache_two', 'Two');
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$this->assertEqual($database_cache->get('cache_two')->data, 'Two');
|
||||
$install_cache->flush();
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
$this->assertFalse($database_cache->get('cache_two'));
|
||||
|
||||
// Store multiple items in the database cache with a temporary expiration,
|
||||
// then use the installer's cache backend to expire outdated items.
|
||||
// Afterwards, confirm that they are no longer in the database cache.
|
||||
$database_cache->set('cache_one', 'One', CACHE_TEMPORARY);
|
||||
$database_cache->set('cache_two', 'Two', CACHE_TEMPORARY);
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$this->assertEqual($database_cache->get('cache_two')->data, 'Two');
|
||||
$install_cache->expire();
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
$this->assertFalse($database_cache->get('cache_two'));
|
||||
|
||||
// Store multiple items in the database cache with a temporary expiration,
|
||||
// then use the installer's cache backend to perform garbage collection.
|
||||
// Afterwards, confirm that they are no longer in the database cache.
|
||||
$database_cache->set('cache_one', 'One', CACHE_TEMPORARY);
|
||||
$database_cache->set('cache_two', 'Two', CACHE_TEMPORARY);
|
||||
$this->assertEqual($database_cache->get('cache_one')->data, 'One');
|
||||
$this->assertEqual($database_cache->get('cache_two')->data, 'Two');
|
||||
// After we've checked that the items are in the cache, we need to enable
|
||||
// garbage collection before running the garbage collector.
|
||||
config('system.performance')->set('cache_lifetime', 1)->save();
|
||||
variable_set('cache_flush_cache_test', 1);
|
||||
$install_cache->garbageCollection();
|
||||
$this->assertFalse($database_cache->get('cache_one'));
|
||||
$this->assertFalse($database_cache->get('cache_two'));
|
||||
|
||||
// Invalidate a tag using the installer cache, then check that the
|
||||
// invalidation was recorded correctly in the database.
|
||||
$install_cache->invalidateTags(array('tag'));
|
||||
$invalidations = db_query("SELECT invalidations FROM {cache_tags} WHERE tag = 'tag'")->fetchField();
|
||||
$this->assertEqual($invalidations, 1);
|
||||
|
||||
// For each cache clearing event that we tried above, try it again after
|
||||
// dropping the {cache_test} table. This simulates the early stages of the
|
||||
// installer (when the database cache tables won't be available yet) and
|
||||
// thereby confirms that the installer's cache backend does not produce
|
||||
// errors if the installer ever calls any code early on that tries to clear
|
||||
// items from the cache.
|
||||
db_drop_table('cache_test');
|
||||
try {
|
||||
$install_cache->isEmpty();
|
||||
$install_cache->delete('cache_one');
|
||||
$install_cache->deleteMultiple(array('cache_one', 'cache_two'));
|
||||
$install_cache->deletePrefix('cache_');
|
||||
$install_cache->flush();
|
||||
$install_cache->expire();
|
||||
$install_cache->garbageCollection();
|
||||
$install_cache->invalidateTags(array('tag'));
|
||||
$this->pass("The installer's cache backend can be used even when the cache database tables are unavailable.");
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->fail("The installer's cache backend can be used even when the cache database tables are unavailable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
name = "Cache test"
|
||||
description = "Support module for cache system testing."
|
||||
package = Testing
|
||||
version = VERSION
|
||||
core = 8.x
|
||||
hidden = TRUE
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the cache_test module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function cache_test_schema() {
|
||||
$schema['cache_test'] = drupal_get_schema_unprocessed('system', 'cache');
|
||||
$schema['cache_test']['description'] = 'Cache table for testing the cache system.';
|
||||
return $schema;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Support module for testing the cache system.
|
||||
*/
|
Loading…
Reference in New Issue