Issue #1371484 by catch, makara, ArtistConk: Fixed Private properties in abstract class DrupalCacheArray.
parent
9bd6e3cafa
commit
a1b360ece1
|
@ -296,12 +296,12 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
/**
|
||||
* A cid to pass to cache()->set() and cache()->get().
|
||||
*/
|
||||
private $cid;
|
||||
protected $cid;
|
||||
|
||||
/**
|
||||
* A bin to pass to cache()->set() and cache()->get().
|
||||
*/
|
||||
private $bin;
|
||||
protected $bin;
|
||||
|
||||
/**
|
||||
* An array of keys to add to the cache at the end of the request.
|
||||
|
@ -400,24 +400,20 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
/**
|
||||
* Writes a value to the persistent cache immediately.
|
||||
*
|
||||
* @param $cid
|
||||
* The cache ID.
|
||||
* @param $bin
|
||||
* The cache bin.
|
||||
* @param $data
|
||||
* The data to write to the persistent cache.
|
||||
* @param $lock
|
||||
* Whether to acquire a lock before writing to cache.
|
||||
*/
|
||||
protected function set($cid, $data, $bin, $lock = TRUE) {
|
||||
protected function set($data, $lock = TRUE) {
|
||||
// Lock cache writes to help avoid stampedes.
|
||||
// To implement locking for cache misses, override __construct().
|
||||
$lock_name = $cid . ':' . $bin;
|
||||
$lock_name = $this->cid . ':' . $this->bin;
|
||||
if (!$lock || lock_acquire($lock_name)) {
|
||||
if ($cached = cache($bin)->get($cid)) {
|
||||
if ($cached = cache($this->bin)->get($this->cid)) {
|
||||
$data = $cached->data + $data;
|
||||
}
|
||||
cache($bin)->set($cid, $data);
|
||||
cache($this->bin)->set($this->cid, $data);
|
||||
if ($lock) {
|
||||
lock_release($lock_name);
|
||||
}
|
||||
|
@ -435,7 +431,7 @@ abstract class DrupalCacheArray implements ArrayAccess {
|
|||
}
|
||||
}
|
||||
if (!empty($data)) {
|
||||
$this->set($this->cid, $data, $this->bin);
|
||||
$this->set($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2336,7 +2336,7 @@ function l($text, $path, array $options = array()) {
|
|||
// rendering.
|
||||
if (variable_get('theme_link', TRUE)) {
|
||||
drupal_theme_initialize();
|
||||
$registry = theme_get_registry();
|
||||
$registry = theme_get_registry(FALSE);
|
||||
// We don't want to duplicate functionality that's in theme(), so any
|
||||
// hint of a module or theme doing anything at all special with the 'link'
|
||||
// theme hook should simply result in theme() being called. This includes
|
||||
|
|
|
@ -372,23 +372,31 @@ class ThemeRegistry Extends DrupalCacheArray {
|
|||
$data = $cached->data;
|
||||
}
|
||||
else {
|
||||
$complete_registry = theme_get_registry();
|
||||
// If there is no runtime cache stored, fetch the full theme registry,
|
||||
// but then initialize each value to NULL. This allows offsetExists()
|
||||
// to function correctly on non-registered theme hooks without triggering
|
||||
// a call to resolveCacheMiss().
|
||||
$data = $this->initializeRegistry();
|
||||
if ($this->persistable) {
|
||||
// If there is no runtime cache stored, fetch the full theme registry,
|
||||
// but then initialize each value to NULL. This allows
|
||||
// offsetExists() to function correctly on non-registered theme hooks
|
||||
// without triggering a call to resolveCacheMiss().
|
||||
$data = array_fill_keys(array_keys($complete_registry), NULL);
|
||||
$this->set($this->cid, $data, $this->bin);
|
||||
$this->completeRegistry = $complete_registry;
|
||||
}
|
||||
else {
|
||||
$data = $complete_registry;
|
||||
$this->set($data);
|
||||
}
|
||||
}
|
||||
$this->storage = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the full theme registry.
|
||||
*
|
||||
* @return
|
||||
* An array with the keys of the full theme registry, but the values
|
||||
* initialized to NULL.
|
||||
*/
|
||||
function initializeRegistry() {
|
||||
$this->completeRegistry = theme_get_registry();
|
||||
|
||||
return array_fill_keys(array_keys($this->completeRegistry), NULL);
|
||||
}
|
||||
|
||||
public function offsetExists($offset) {
|
||||
// Since the theme registry allows for theme hooks to be requested that
|
||||
// are not registered, just check the existence of the key in the registry.
|
||||
|
@ -420,15 +428,19 @@ class ThemeRegistry Extends DrupalCacheArray {
|
|||
return $this->storage[$offset];
|
||||
}
|
||||
|
||||
public function set($cid, $data, $bin, $lock = TRUE) {
|
||||
$lock_name = $cid . ':' . $bin;
|
||||
public function set($data, $lock = TRUE) {
|
||||
$lock_name = $this->cid . ':' . $this->bin;
|
||||
if (!$lock || lock_acquire($lock_name)) {
|
||||
if ($cached = cache($bin)->get($cid)) {
|
||||
if ($cached = cache($this->bin)->get($this->cid)) {
|
||||
// Use array merge instead of union so that filled in values in $data
|
||||
// overwrite empty values in the current cache.
|
||||
$data = array_merge($cached->data, $data);
|
||||
}
|
||||
cache($bin)->set($cid, $data);
|
||||
else {
|
||||
$registry = $this->initializeRegistry();
|
||||
$data = array_merge($registry, $data);
|
||||
}
|
||||
cache($this->bin)->set($this->cid, $data);
|
||||
if ($lock) {
|
||||
lock_release($lock_name);
|
||||
}
|
||||
|
|
|
@ -541,3 +541,54 @@ class ThemeHtmlTplPhpAttributesTestCase extends DrupalWebTestCase {
|
|||
$this->assertTrue(count($attributes) == 1, t('Attribute set in the body element via hook_preprocess_html() found.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for the ThemeRegistry class.
|
||||
*/
|
||||
class ThemeRegistryTestCase extends DrupalWebTestCase {
|
||||
protected $profile = 'testing';
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'ThemeRegistry',
|
||||
'description' => 'Tests the behavior of the ThemeRegistry class',
|
||||
'group' => 'Theme',
|
||||
);
|
||||
}
|
||||
function setUp() {
|
||||
parent::setUp('theme_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the theme registry class.
|
||||
*/
|
||||
function testRaceCondition() {
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$cid = 'test_theme_registry';
|
||||
|
||||
// Directly instantiate the theme registry, this will cause a base cache
|
||||
// entry to be written in __construct().
|
||||
$registry = new ThemeRegistry($cid, 'cache');
|
||||
|
||||
$this->assertTrue(cache()->get($cid), 'Cache entry was created.');
|
||||
|
||||
// Trigger a cache miss for an offset.
|
||||
$this->assertTrue($registry['theme_test_template_test'], 'Offset was returned correctly from the theme registry.');
|
||||
// This will cause the ThemeRegistry class to write an updated version of
|
||||
// the cache entry when it is destroyed, usually at the end of the request.
|
||||
// Before that happens, manually delete the cache entry we created earlier
|
||||
// so that the new entry is written from scratch.
|
||||
cache()->delete($cid);
|
||||
|
||||
// Destroy the class so that it triggers a cache write for the offset.
|
||||
unset($registry);
|
||||
|
||||
$this->assertTrue(cache()->get($cid), 'Cache entry was created.');
|
||||
|
||||
// Create a new instance of the class. Confirm that both the offset
|
||||
// requested previously, and one that has not yet been requested are both
|
||||
// available.
|
||||
$registry = new ThemeRegistry($cid, 'cache');
|
||||
$this->assertTrue($registry['theme_test_template_test'], 'Offset was returned correctly from the theme registry');
|
||||
$this->assertTrue($registry['theme_test_template_test_2'], 'Offset was returned correctly from the theme registry');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ function theme_test_theme($existing, $type, $theme, $path) {
|
|||
$items['theme_test_template_test'] = array(
|
||||
'template' => 'theme_test.template_test',
|
||||
);
|
||||
$items['theme_test_template_test_2'] = array(
|
||||
'template' => 'theme_test.template_test',
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue