From 2370dd0b38b71726ab1ba83f1b6d0ef67becaf3b Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Tue, 26 May 2009 03:46:04 +0000 Subject: [PATCH] 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 --- core/Extension.php | 15 +++++++++++++-- core/Object.php | 2 +- core/model/DataObjectDecorator.php | 23 ++++++++++++++--------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/core/Extension.php b/core/Extension.php index deb5b1b91..11902448c 100644 --- a/core/Extension.php +++ b/core/Extension.php @@ -23,12 +23,23 @@ abstract class Extension extends Object { * @var DataObject */ protected $owner; + + /** + * The base class that this extension was applied to; $this->owner must be one of these + * @var DataObject + */ + protected $ownerBaseClass; /** * Set the owner of this decorator. - * @param DataObject $owner + * @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) { + function setOwner(Object $owner, $ownerBaseClass = null) { + $this->ownerBaseClass = $ownerBaseClass ? $ownerBaseClass : $owner->class; $this->owner = $owner; } diff --git a/core/Object.php b/core/Object.php index f49585d6c..2298d2c8f 100755 --- a/core/Object.php +++ b/core/Object.php @@ -453,7 +453,7 @@ abstract class Object { // an $extension value can contain parameters as a string, // e.g. "Versioned('Stage','Live')" $instance = eval("return new $extension;"); - $instance->setOwner($this); + $instance->setOwner($this, $class); $this->extension_instances[$instance->class] = $instance; } } diff --git a/core/model/DataObjectDecorator.php b/core/model/DataObjectDecorator.php index 58a1262dc..8eb672a78 100755 --- a/core/model/DataObjectDecorator.php +++ b/core/model/DataObjectDecorator.php @@ -31,11 +31,13 @@ abstract class DataObjectDecorator extends Extension { 'api_access' => false, ); + private static $extra_statics_loaded = array(); + /** * Set the owner of this decorator. * @param DataObject $owner */ - function setOwner(Object $owner) { + function setOwner(Object $owner, $ownerBaseClass = null) { if(!($owner instanceof DataObject)) { user_error(sprintf( "DataObjectDecorator->setOwner(): Trying to decorate an object of class '%s' with '%s', @@ -46,35 +48,38 @@ abstract class DataObjectDecorator extends Extension { return false; } - parent::setOwner($owner); + parent::setOwner($owner, $ownerBaseClass); } /** * Load the extra database fields defined in extraStatics. */ function loadExtraStatics() { - // Don't apply DB fields if the parent object has this extension too - if(Object::has_extension($this->owner->parentClass(), $this->class)) return; + if(!empty(self::$extra_statics_loaded[$this->ownerBaseClass][$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()) { foreach($fields as $relation => $newVal) { 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 if(self::$decoratable_statics[$relation]) { // 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 } 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_field[$this->owner->class] = null; + DataObject::$cache_has_own_table[$this->ownerBaseClass] = null; + DataObject::$cache_has_own_table_field[$this->ownerBaseClass] = null; } }