Issue #3136041 by jweowu: drupal_static() edge case bug and inconsistent comments

merge-requests/3778/head
catch 2023-04-04 09:02:50 +01:00
parent 7ea52649ec
commit d070ec1d3f
2 changed files with 49 additions and 25 deletions

View File

@ -429,37 +429,42 @@ function drupal_maintenance_theme() {
* @see drupal_static_reset() * @see drupal_static_reset()
*/ */
function &drupal_static($name, $default_value = NULL, $reset = FALSE) { function &drupal_static($name, $default_value = NULL, $reset = FALSE) {
static $data = [], $default = []; static $data = [], $defaults = [];
// First check if dealing with a previously defined static variable. if (isset($name)) {
if (isset($data[$name]) || array_key_exists($name, $data)) { // Check if we're dealing with a previously defined static variable.
// Non-NULL $name and both $data[$name] and $default[$name] statics exist. if (\array_key_exists($name, $data)) {
// Both $data[$name] and (implicitly) $defaults[$name] statics exist.
if ($reset) { if ($reset) {
// Reset pre-existing static variable to its default value. // Reset pre-existing static variable to its default value.
$data[$name] = $default[$name]; $data[$name] = $defaults[$name];
} }
return $data[$name];
} }
// Neither $data[$name] nor $default[$name] static variables exist. else {
if (isset($name)) { // Neither $data[$name] nor $defaults[$name] static variables exist.
if ($reset) { if ($reset) {
// Reset was called before a default is set and yet a variable must be // Reset was called before any value for $name was set, so we should
// returned. // not set anything ($default_value is not reliable in this case). As
// the function returns a reference, we must still return a variable.
// (Code using $reset does not use the return value).
return $data; return $data;
} }
// First call with new non-NULL $name. Initialize a new static variable. // First call with new non-NULL $name. Initialize a new static variable.
$default[$name] = $data[$name] = $default_value; $defaults[$name] = $data[$name] = $default_value;
}
// Return a reference to the named variable.
return $data[$name]; return $data[$name];
} }
else {
// Reset all: ($name == NULL). This needs to be done one at a time so that // Reset all: ($name == NULL). This needs to be done one at a time so that
// references returned by earlier invocations of drupal_static() also get // references returned by earlier invocations of drupal_static() also get
// reset. // reset.
foreach ($default as $name => $value) { foreach ($defaults as $name => $value) {
$data[$name] = $value; $data[$name] = $value;
} }
// As the function returns a reference, the return should always be a // As the function returns a reference, we must still return a variable.
// variable.
return $data; return $data;
} }
}
/** /**
* Resets one or all centrally stored static variable(s). * Resets one or all centrally stored static variable(s).

View File

@ -36,6 +36,25 @@ class ResettableStaticTest extends KernelTestBase {
$var = 'bar'; $var = 'bar';
drupal_static_reset(); drupal_static_reset();
$this->assertEquals('foo', $var, 'Variable was reset after second invocation of global reset.'); $this->assertEquals('foo', $var, 'Variable was reset after second invocation of global reset.');
// Test calling drupal_static() with no arguments (empty string).
$name1 = __CLASS__ . '_' . __METHOD__ . '1';
$name2 = '';
$var1 = &drupal_static($name1, 'initial1');
$var2 = &drupal_static($name2, 'initial2');
$this->assertEquals('initial1', $var1, 'Variable 1 returned by drupal_static() was set to its default.');
$this->assertEquals('initial2', $var2, 'Variable 2 returned by drupal_static() was set to its default.');
$var1 = 'modified1';
$var2 = 'modified2';
drupal_static_reset($name1);
drupal_static_reset($name2);
$this->assertEquals('initial1', $var1, 'Variable 1 was reset after invocation of name-specific reset.');
$this->assertEquals('initial2', $var2, 'Variable 2 was reset after invocation of name-specific reset.');
$var1 = 'modified1';
$var2 = 'modified2';
drupal_static_reset();
$this->assertEquals('initial1', $var1, 'Variable 1 was reset after invocation of global reset.');
$this->assertEquals('initial2', $var2, 'Variable 2 was reset after invocation of global reset.');
} }
} }