mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 12:05:37 +00:00
FIX If ClassName read from DB doesnt exist, dont break
We know the subclass of a record by its ClassName value, but code changes might have meant that class no longer exists. We used to just break, but this patch overrides the apparent value of ClassName to be one that exists in that situation
This commit is contained in:
parent
cc2e250719
commit
2f00884e79
@ -58,8 +58,10 @@ class ClassInfo {
|
|||||||
* Returns the manifest of all classes which are present in the database.
|
* Returns the manifest of all classes which are present in the database.
|
||||||
* @param string $class Class name to check enum values for ClassName field
|
* @param string $class Class name to check enum values for ClassName field
|
||||||
*/
|
*/
|
||||||
static function getValidSubClasses($class = 'SiteTree') {
|
static function getValidSubClasses($class = 'SiteTree', $includeUnbacked = false) {
|
||||||
return DB::getConn()->enumValuesForField($class, 'ClassName');
|
$classes = DB::getConn()->enumValuesForField($class, 'ClassName');
|
||||||
|
if (!$includeUnbacked) $classes = array_filter($classes, array('ClassInfo', 'exists'));
|
||||||
|
return $classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,9 +181,12 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
*/
|
*/
|
||||||
public static function database_fields($class) {
|
public static function database_fields($class) {
|
||||||
if(get_parent_class($class) == 'DataObject') {
|
if(get_parent_class($class) == 'DataObject') {
|
||||||
|
$db = DB::getConn();
|
||||||
|
$existing = $db->hasField($class, 'ClassName') ? $db->query("SELECT DISTINCT \"ClassName\" FROM \"$class\"")->column() : array();
|
||||||
|
|
||||||
return array_merge (
|
return array_merge (
|
||||||
array (
|
array (
|
||||||
'ClassName' => "Enum('" . implode(', ', ClassInfo::subclassesFor($class)) . "')",
|
'ClassName' => "Enum('" . implode(', ', array_unique(array_merge($existing, ClassInfo::subclassesFor($class)))) . "')",
|
||||||
'Created' => 'SS_Datetime',
|
'Created' => 'SS_Datetime',
|
||||||
'LastEdited' => 'SS_Datetime'
|
'LastEdited' => 'SS_Datetime'
|
||||||
),
|
),
|
||||||
@ -444,6 +447,17 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getObsoleteClassName() {
|
||||||
|
$className = $this->getField("ClassName");
|
||||||
|
if (!ClassInfo::exists($className)) return $className;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getClassName() {
|
||||||
|
$className = $this->getField("ClassName");
|
||||||
|
if (!ClassInfo::exists($className)) return get_class($this);
|
||||||
|
return $className;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the ClassName attribute. {@link $class} is also updated.
|
* Set the ClassName attribute. {@link $class} is also updated.
|
||||||
* Warning: This will produce an inconsistent record, as the object
|
* Warning: This will produce an inconsistent record, as the object
|
||||||
@ -986,16 +1000,33 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
$this->brokenOnWrite = true;
|
$this->brokenOnWrite = true;
|
||||||
$isNewRecord = false;
|
$isNewRecord = false;
|
||||||
|
|
||||||
if(self::get_validation_enabled()) {
|
$writeException = null;
|
||||||
|
|
||||||
|
if ($this->ObsoleteClassName) {
|
||||||
|
$writeException = new ValidationException(
|
||||||
|
"Object is of class '{$this->ObsoleteClassName}' which doesn't exist - ".
|
||||||
|
"you need to change the ClassName before you can write it",
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if(self::get_validation_enabled()) {
|
||||||
$valid = $this->validate();
|
$valid = $this->validate();
|
||||||
if(!$valid->valid()) {
|
if (!$valid->valid()) {
|
||||||
// Used by DODs to clean up after themselves, eg, Versioned
|
$writeException = new ValidationException(
|
||||||
$this->extend('onAfterSkippedWrite');
|
$valid,
|
||||||
throw new ValidationException($valid, "Validation error writing a $this->class object: " . $valid->message() . ". Object not written.", E_USER_WARNING);
|
"Validation error writing a $this->class object: " . $valid->message() . ". Object not written.",
|
||||||
return false;
|
E_USER_WARNING
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($writeException) {
|
||||||
|
// Used by DODs to clean up after themselves, eg, Versioned
|
||||||
|
$this->extend('onAfterSkippedWrite');
|
||||||
|
throw $writeException;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$this->onBeforeWrite();
|
$this->onBeforeWrite();
|
||||||
if($this->brokenOnWrite) {
|
if($this->brokenOnWrite) {
|
||||||
user_error("$this->class has a broken onBeforeWrite() function. Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
|
user_error("$this->class has a broken onBeforeWrite() function. Make sure that you call parent::onBeforeWrite().", E_USER_ERROR);
|
||||||
|
@ -1103,7 +1103,7 @@ class Versioned_Version extends ViewableData {
|
|||||||
$record['ID'] = $record['RecordID'];
|
$record['ID'] = $record['RecordID'];
|
||||||
$className = $record['ClassName'];
|
$className = $record['ClassName'];
|
||||||
|
|
||||||
$this->object = new $className($record);
|
$this->object = ClassInfo::exists($className) ? new $className($record) : new DataObject($record);
|
||||||
$this->failover = $this->object;
|
$this->failover = $this->object;
|
||||||
|
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user