mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
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:
parent
6eb61e0844
commit
2370dd0b38
@ -23,12 +23,23 @@ abstract class Extension extends Object {
|
|||||||
* @var DataObject
|
* @var DataObject
|
||||||
*/
|
*/
|
||||||
protected $owner;
|
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.
|
* 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;
|
$this->owner = $owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user