Skip to content

Commit

Permalink
API CHANGE: Make Object::uninherited_static() have a separate executi…
Browse files Browse the repository at this point in the history
…on path to Object::get_static(), for more reliable operation. The intention is that for any given static, you either use Object::get_static() or you use Object::uninherited_static() - not both. (from r84151, r84155, r84156)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.3@84157 467b73ca-7a2a-4603-9d3b-597d59a354a9
  • Loading branch information
Sam Minnee committed Feb 2, 2011
1 parent 3884665 commit 427cce4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 34 deletions.
67 changes: 46 additions & 21 deletions core/Object.php
Expand Up @@ -41,10 +41,12 @@ abstract class Object {
*/

private static
$statics = array(),
$cached_statics = array(),
$extra_statics = array(),
$replaced_statics = array(),
$statics = array(),
$cached_statics = array(),
$uninherited_statics = array(),
$cached_uninherited_statics = array(),
$extra_statics = array(),
$replaced_statics = array(),
$_cache_statics_prepared = array();

private static
Expand Down Expand Up @@ -231,7 +233,7 @@ public static function get_static($class, $name, $uncached = false) {

return self::$statics[$class][$name];
}

/**
* Set a static variable
*
Expand All @@ -244,10 +246,12 @@ public static function set_static($class, $name, $value) {
Object::prepare_statics($class);
}

self::$statics[$class][$name] = $value;
self::$statics[$class][$name] = $value;
self::$uninherited_statics[$class][$name] = $value;
self::$cached_statics[$class][$name] = true;
self::$cached_uninherited_statics[$class][$name] = true;
}

/**
* Get an uninherited static variable - a variable that is explicity set in this class, and not in the parent class.
*
Expand All @@ -260,19 +264,33 @@ public static function set_static($class, $name, $value) {
* @param string $name
* @return mixed
*/
public static function uninherited_static($class, $name) {
$inherited = self::get_static($class, $name);
$parent = null;

if($parentClass = get_parent_class($class)) {
$parent = self::get_static($parentClass, $name);
public static function uninherited_static($class, $name, $uncached = false) {
if(!isset(self::$_cache_statics_prepared[$class])) {
Object::prepare_statics($class);
}

if(is_array($inherited) && is_array($parent)) {
return array_diff_assoc($inherited, $parent);
if(!isset(self::$cached_uninherited_statics[$class][$name]) || $uncached) {
$classRef = new ReflectionClass($class);
$classProps = $classRef->getStaticProperties();

$parentClass = get_parent_class($class);
if($parentClass) {
$parentRef = new ReflectionClass($parentClass);
$parentProps = $parentRef->getStaticProperties();

$uninheritedBuiltIn = isset($classProps[$name])
&& (!isset($parentProps[$name])
|| $classProps[$name] != $parentProps[$name]) ? $classProps[$name] : null;
} else {
$uninheritedBuiltIn = isset($classProps[$name]) ? $classProps[$name] : null;
}


self::$cached_uninherited_statics[$class][$name] = true;
self::$uninherited_statics[$class][$name] = $uninheritedBuiltIn;
}
return ($inherited != $parent) ? $inherited : null;

return self::$uninherited_statics[$class][$name];
}

/**
Expand Down Expand Up @@ -356,7 +374,7 @@ public static function add_static_var($class, $name, $value, $replace = false) {
*/
public static function has_extension($class, $requiredExtension) {
$requiredExtension = strtolower($requiredExtension);
if($extensions = self::get_static($class, 'extensions')) foreach($extensions as $extension) {
if($extensions = self::combined_static($class, 'extensions')) foreach($extensions as $extension) {
$left = strtolower(Extension::get_classname_without_arguments($extension));
$right = strtolower(Extension::get_classname_without_arguments($requiredExtension));
if($left == $right) return true;
Expand Down Expand Up @@ -399,7 +417,14 @@ public static function add_extension($class, $extension) {
}

// merge with existing static vars
self::add_static_var($class, 'extensions', array($extension));
$extensions = self::uninherited_static($class, 'extensions');

// We use unshift rather than push so that module extensions are added before built-in ones.
// in particular, this ensures that the Versioned rewriting is done last.
if($extensions) array_unshift($extensions, $extension);
else $extensions = array($extension);

self::set_static($class, 'extensions', $extensions);

// load statics now for DataObject classes
if(is_subclass_of($class, 'DataObject')) {
Expand All @@ -418,7 +443,7 @@ private static function prepare_statics($class) {

// load statics now for DataObject classes
if(is_subclass_of($class, 'DataObject')) {
$extensions = Object::get_static($class, 'extensions');
$extensions = Object::uninherited_static($class, 'extensions');
if($extensions) foreach($extensions as $extension) {
if(preg_match('/^([^(]*)/', $extension, $matches)) {
$extensionClass = $matches[1];
Expand Down Expand Up @@ -450,7 +475,7 @@ public static function remove_extension($class, $extension) {
self::set_static(
$class,
'extensions',
array_diff(self::get_static($class, 'extensions'), array($extension))
array_diff(self::uninherited_static($class, 'extensions'), array($extension))
);
}

Expand Down
24 changes: 12 additions & 12 deletions core/model/DataObject.php
Expand Up @@ -723,7 +723,7 @@ public function populateDefaults() {
$classes = array_reverse(ClassInfo::ancestry($this));

foreach($classes as $class) {
$defaults = Object::get_static($class, 'defaults');
$defaults = Object::uninherited_static($class, 'defaults');

if($defaults) foreach($defaults as $fieldName => $fieldValue) {
// SRM 2007-03-06: Stricter check
Expand Down Expand Up @@ -1336,13 +1336,13 @@ public function has_one($component = null) {
if(in_array($class, array('Object', 'ViewableData', 'DataObject'))) continue;

if($component) {
$hasOne = Object::get_static($class, 'has_one');
$hasOne = Object::uninherited_static($class, 'has_one');

if(isset($hasOne[$component])) {
return $hasOne[$component];
}
} else {
$newItems = (array) Object::get_static($class, 'has_one');
$newItems = (array) Object::uninherited_static($class, 'has_one');
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$has_one has a bad entry: "
Expand Down Expand Up @@ -1375,13 +1375,13 @@ public function db($component = null) {
}

if($component) {
$db = Object::get_static($class, 'db');
$db = Object::uninherited_static($class, 'db');

if(isset($db[$component])) {
return $db[$component];
}
} else {
$newItems = (array) Object::get_static($class, 'db');
$newItems = (array) Object::uninherited_static($class, 'db');
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$db has a bad entry: "
Expand Down Expand Up @@ -1409,13 +1409,13 @@ public function has_many($component = null) {
if(in_array($class, array('ViewableData', 'Object', 'DataObject'))) continue;

if($component) {
$hasMany = Object::get_static($class, 'has_many');
$hasMany = Object::uninherited_static($class, 'has_many');

if(isset($hasMany[$component])) {
return $hasMany[$component];
}
} else {
$newItems = (array) Object::get_static($class, 'has_many');
$newItems = (array) Object::uninherited_static($class, 'has_many');
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$has_many has a bad entry: "
Expand Down Expand Up @@ -1529,7 +1529,7 @@ public function many_many($component = null) {
if(in_array($class, array('ViewableData', 'Object', 'DataObject'))) continue;

if($component) {
$manyMany = Object::get_static($class, 'many_many');
$manyMany = Object::uninherited_static($class, 'many_many');
// Try many_many
$candidate = (isset($manyMany[$component])) ? $manyMany[$component] : null;
if($candidate) {
Expand All @@ -1539,13 +1539,13 @@ public function many_many($component = null) {
}

// Try belongs_many_many
$belongsManyMany = Object::get_static($class, 'belongs_many_many');
$belongsManyMany = Object::uninherited_static($class, 'belongs_many_many');
$candidate = (isset($belongsManyMany[$component])) ? $belongsManyMany[$component] : null;
if($candidate) {
$childField = $candidate . "ID";

// We need to find the inverse component name
$otherManyMany = Object::get_static($candidate, 'many_many');
$otherManyMany = Object::uninherited_static($candidate, 'many_many');
if(!$otherManyMany) {
user_error("Inverse component of $candidate not found ({$this->class})", E_USER_ERROR);
}
Expand All @@ -1564,15 +1564,15 @@ public function many_many($component = null) {
user_error("Orphaned \$belongs_many_many value for $this->class.$component", E_USER_ERROR);
}
} else {
$newItems = (array) Object::get_static($class, 'many_many');
$newItems = (array) Object::uninherited_static($class, 'many_many');
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$many_many has a bad entry: "
. var_export($k,true). " => " . var_export($v,true) . ". Each map key should be a relationship name, and the map value should be the data class to join to.", E_USER_ERROR);
}
$items = isset($items) ? array_merge($newItems, $items) : $newItems;

$newItems = (array) Object::get_static($class, 'belongs_many_many');
$newItems = (array) Object::uninherited_static($class, 'belongs_many_many');
// Validate the data
foreach($newItems as $k => $v) {
if(!is_string($k) || is_numeric($k) || !is_string($v)) user_error("$class::\$belongs_many_many has a bad entry: "
Expand Down
2 changes: 1 addition & 1 deletion core/model/DataObjectDecorator.php
Expand Up @@ -69,10 +69,10 @@ public static function load_extra_statics($class, $extension) {
if($statics) {
foreach($statics as $name => $newVal) {
if(isset(self::$decoratable_statics[$name])) {
$origVal = self::get_static($class, $name);

// Array to be merged
if(self::$decoratable_statics[$name]) {
$origVal = self::uninherited_static($class, $name);
// Can't use add_static_var() here as it would merge the array rather than replacing
self::set_static($class, $name, array_merge((array)$origVal, $newVal));

Expand Down
11 changes: 11 additions & 0 deletions tests/ObjectStaticTest.php
Expand Up @@ -52,6 +52,17 @@ public function testUninherited() {
$this->assertEquals(Object::uninherited_static('ObjectStaticTest_Fourth', 'third', true), null);
}

/**
* Confirms that Object::add_static_var() doesn't work for uninherited stats
*/
public function testAddStaticVarDoesntWorkFor() {
Object::add_static_var('ObjectStaticTest_First', 'first', array('test_1b'));
Object::add_static_var('ObjectStaticTest_Second', 'first', array('test_2b'));

$this->assertNotContains('test_1b', Object::uninherited_static('ObjectStaticTest_First', 'first'));
$this->assertNotContains('test_2b', Object::uninherited_static('ObjectStaticTest_Second', 'first'));
}

}

/**#@+
Expand Down

0 comments on commit 427cce4

Please sign in to comment.