BUGFIX: Fixed edge-case reliability with extension application.

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@77828 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2009-05-26 03:46:04 +00:00
parent 6eb61e0844
commit 2370dd0b38
3 changed files with 28 additions and 12 deletions

View File

@ -25,10 +25,21 @@ abstract class Extension extends Object {
protected $owner; protected $owner;
/** /**
* Set the owner of this decorator. * The base class that this extension was applied to; $this->owner must be one of these
* @param DataObject $owner * @var DataObject
*/ */
function setOwner(Object $owner) { protected $ownerBaseClass;
/**
* Set the owner of this decorator.
* @param Object $owner The owner object,
* @param string $ownerBaseClass The base class that the extension is applied to; this may be
* the class of owner, or it may be a parent. For example, if Versioned was applied to SiteTree,
* and then a Page object was instantiated, $owner would be a Page object, but $ownerBaseClass
* would be 'SiteTree'.
*/
function setOwner(Object $owner, $ownerBaseClass = null) {
$this->ownerBaseClass = $ownerBaseClass ? $ownerBaseClass : $owner->class;
$this->owner = $owner; $this->owner = $owner;
} }

View File

@ -453,7 +453,7 @@ abstract class Object {
// an $extension value can contain parameters as a string, // an $extension value can contain parameters as a string,
// e.g. "Versioned('Stage','Live')" // e.g. "Versioned('Stage','Live')"
$instance = eval("return new $extension;"); $instance = eval("return new $extension;");
$instance->setOwner($this); $instance->setOwner($this, $class);
$this->extension_instances[$instance->class] = $instance; $this->extension_instances[$instance->class] = $instance;
} }
} }

View File

@ -31,11 +31,13 @@ abstract class DataObjectDecorator extends Extension {
'api_access' => false, 'api_access' => false,
); );
private static $extra_statics_loaded = array();
/** /**
* Set the owner of this decorator. * Set the owner of this decorator.
* @param DataObject $owner * @param DataObject $owner
*/ */
function setOwner(Object $owner) { function setOwner(Object $owner, $ownerBaseClass = null) {
if(!($owner instanceof DataObject)) { if(!($owner instanceof DataObject)) {
user_error(sprintf( user_error(sprintf(
"DataObjectDecorator->setOwner(): Trying to decorate an object of class '%s' with '%s', "DataObjectDecorator->setOwner(): Trying to decorate an object of class '%s' with '%s',
@ -46,35 +48,38 @@ abstract class DataObjectDecorator extends Extension {
return false; return false;
} }
parent::setOwner($owner); parent::setOwner($owner, $ownerBaseClass);
} }
/** /**
* Load the extra database fields defined in extraStatics. * Load the extra database fields defined in extraStatics.
*/ */
function loadExtraStatics() { function loadExtraStatics() {
// Don't apply DB fields if the parent object has this extension too if(!empty(self::$extra_statics_loaded[$this->ownerBaseClass][$this->class])) return;
if(Object::has_extension($this->owner->parentClass(), $this->class)) return; self::$extra_statics_loaded[$this->ownerBaseClass][$this->class] = true;
// If the extension has been manually applied to a subclass, we should ignore that.
if(Object::has_extension(get_parent_class($this->owner), $this->class)) return;
if($fields = $this->extraStatics()) { if($fields = $this->extraStatics()) {
foreach($fields as $relation => $newVal) { foreach($fields as $relation => $newVal) {
if(isset(self::$decoratable_statics[$relation])) { if(isset(self::$decoratable_statics[$relation])) {
$origVal = Object::get_static($this->owner->class, $relation); $origVal = Object::get_static($this->ownerBaseClass, $relation);
// Array to be merged // Array to be merged
if(self::$decoratable_statics[$relation]) { if(self::$decoratable_statics[$relation]) {
// Can't use add_static_var() here as it would merge the array rather than replacing // Can't use add_static_var() here as it would merge the array rather than replacing
Object::set_static($this->owner->class, $relation, array_merge((array)$origVal, $newVal)); Object::set_static($this->ownerBaseClass, $relation, array_merge((array)$origVal, $newVal));
// Value to be overwritten // Value to be overwritten
} else { } else {
Object::set_static ($this->owner->class, $relation, $newVal); Object::set_static ($this->ownerBaseClass, $relation, $newVal);
} }
} }
} }
DataObject::$cache_has_own_table[$this->owner->class] = null; DataObject::$cache_has_own_table[$this->ownerBaseClass] = null;
DataObject::$cache_has_own_table_field[$this->owner->class] = null; DataObject::$cache_has_own_table_field[$this->ownerBaseClass] = null;
} }
} }