mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge branch '4.6' into 4.7
This commit is contained in:
commit
b0762593da
@ -3,12 +3,14 @@
|
|||||||
namespace SilverStripe\ORM;
|
namespace SilverStripe\ORM;
|
||||||
|
|
||||||
use BadMethodCallException;
|
use BadMethodCallException;
|
||||||
|
use Generator;
|
||||||
use SilverStripe\Control\Controller;
|
use SilverStripe\Control\Controller;
|
||||||
use SilverStripe\Control\Director;
|
use SilverStripe\Control\Director;
|
||||||
use SilverStripe\Core\ClassInfo;
|
use SilverStripe\Core\ClassInfo;
|
||||||
use SilverStripe\Core\Environment;
|
use SilverStripe\Core\Environment;
|
||||||
use SilverStripe\Core\Injector\Injector;
|
use SilverStripe\Core\Injector\Injector;
|
||||||
use SilverStripe\Core\Manifest\ClassLoader;
|
use SilverStripe\Core\Manifest\ClassLoader;
|
||||||
|
use SilverStripe\Dev\Deprecation;
|
||||||
use SilverStripe\Dev\DevelopmentAdmin;
|
use SilverStripe\Dev\DevelopmentAdmin;
|
||||||
use SilverStripe\Dev\TestOnly;
|
use SilverStripe\Dev\TestOnly;
|
||||||
use SilverStripe\ORM\Connect\DatabaseException;
|
use SilverStripe\ORM\Connect\DatabaseException;
|
||||||
@ -38,17 +40,17 @@ class DatabaseAdmin extends Controller
|
|||||||
* Obsolete classname values that should be remapped in dev/build
|
* Obsolete classname values that should be remapped in dev/build
|
||||||
*/
|
*/
|
||||||
private static $classname_value_remapping = [
|
private static $classname_value_remapping = [
|
||||||
'File' => 'SilverStripe\\Assets\\File',
|
'File' => 'SilverStripe\\Assets\\File',
|
||||||
'Image' => 'SilverStripe\\Assets\\Image',
|
'Image' => 'SilverStripe\\Assets\\Image',
|
||||||
'Folder' => 'SilverStripe\\Assets\\Folder',
|
'Folder' => 'SilverStripe\\Assets\\Folder',
|
||||||
'Group' => 'SilverStripe\\Security\\Group',
|
'Group' => 'SilverStripe\\Security\\Group',
|
||||||
'LoginAttempt' => 'SilverStripe\\Security\\LoginAttempt',
|
'LoginAttempt' => 'SilverStripe\\Security\\LoginAttempt',
|
||||||
'Member' => 'SilverStripe\\Security\\Member',
|
'Member' => 'SilverStripe\\Security\\Member',
|
||||||
'MemberPassword' => 'SilverStripe\\Security\\MemberPassword',
|
'MemberPassword' => 'SilverStripe\\Security\\MemberPassword',
|
||||||
'Permission' => 'SilverStripe\\Security\\Permission',
|
'Permission' => 'SilverStripe\\Security\\Permission',
|
||||||
'PermissionRole' => 'SilverStripe\\Security\\PermissionRole',
|
'PermissionRole' => 'SilverStripe\\Security\\PermissionRole',
|
||||||
'PermissionRoleCode' => 'SilverStripe\\Security\\PermissionRoleCode',
|
'PermissionRoleCode' => 'SilverStripe\\Security\\PermissionRoleCode',
|
||||||
'RememberLoginHash' => 'SilverStripe\\Security\\RememberLoginHash',
|
'RememberLoginHash' => 'SilverStripe\\Security\\RememberLoginHash',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -207,7 +209,7 @@ class DatabaseAdmin extends Controller
|
|||||||
$file = TEMP_PATH
|
$file = TEMP_PATH
|
||||||
. DIRECTORY_SEPARATOR
|
. DIRECTORY_SEPARATOR
|
||||||
. 'database-last-generated-'
|
. 'database-last-generated-'
|
||||||
. str_replace(['\\','/',':'], '.', Director::baseFolder());
|
. str_replace(['\\', '/', ':'], '.', Director::baseFolder());
|
||||||
|
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
return filemtime($file);
|
return filemtime($file);
|
||||||
@ -219,9 +221,9 @@ class DatabaseAdmin extends Controller
|
|||||||
/**
|
/**
|
||||||
* Updates the database schema, creating tables & fields as necessary.
|
* Updates the database schema, creating tables & fields as necessary.
|
||||||
*
|
*
|
||||||
* @param boolean $quiet Don't show messages
|
* @param boolean $quiet Don't show messages
|
||||||
* @param boolean $populate Populate the database, as well as setting up its schema
|
* @param boolean $populate Populate the database, as well as setting up its schema
|
||||||
* @param bool $testMode
|
* @param bool $testMode
|
||||||
*/
|
*/
|
||||||
public function doBuild($quiet = false, $populate = true, $testMode = false)
|
public function doBuild($quiet = false, $populate = true, $testMode = false)
|
||||||
{
|
{
|
||||||
@ -356,15 +358,7 @@ class DatabaseAdmin extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remap obsolete class names
|
// Remap obsolete class names
|
||||||
$remappingConfig = $this->config()->get('classname_value_remapping');
|
$this->migrateClassNames();
|
||||||
$remappingFields = $this->getClassNameRemappingFields();
|
|
||||||
foreach ($remappingFields as $className => $fieldNames) {
|
|
||||||
foreach ($fieldNames as $fieldName) {
|
|
||||||
foreach ($remappingConfig as $oldClassName => $newClassName) {
|
|
||||||
$this->updateLegacyClassNames($className, $fieldName, $oldClassName, $newClassName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Require all default records
|
// Require all default records
|
||||||
foreach ($dataClasses as $dataClass) {
|
foreach ($dataClasses as $dataClass) {
|
||||||
@ -398,7 +392,7 @@ class DatabaseAdmin extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!$quiet) {
|
if (!$quiet) {
|
||||||
echo (Director::is_cli()) ? "\n Database build completed!\n\n" :"<p>Database build completed!</p>";
|
echo (Director::is_cli()) ? "\n Database build completed!\n\n" : "<p>Database build completed!</p>";
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($dataClasses as $dataClass) {
|
foreach ($dataClasses as $dataClass) {
|
||||||
@ -416,8 +410,23 @@ class DatabaseAdmin extends Controller
|
|||||||
* @param string $fieldName The field name to look in for obsolete class names
|
* @param string $fieldName The field name to look in for obsolete class names
|
||||||
* @param string $oldClassName The old class name
|
* @param string $oldClassName The old class name
|
||||||
* @param string $newClassName The new class name
|
* @param string $newClassName The new class name
|
||||||
|
* @deprecated 5.0 use updateLegacyClassNameField instead
|
||||||
*/
|
*/
|
||||||
protected function updateLegacyClassNames($dataClass, $fieldName, $oldClassName, $newClassName)
|
protected function updateLegacyClassNames($dataClass, $fieldName, $oldClassName, $newClassName)
|
||||||
|
{
|
||||||
|
Deprecation::notice('5.0', 'use updateLegacyClassNameField instead');
|
||||||
|
$this->updateLegacyClassNameField($dataClass, $fieldName, [$oldClassName => $newClassName]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a base data class, a field name and a mapping of class replacements, look for obsolete
|
||||||
|
* values in the $dataClass's $fieldName column and replace it with $mapping
|
||||||
|
*
|
||||||
|
* @param string $dataClass The data class to look up
|
||||||
|
* @param string $fieldName The field name to look in for obsolete class names
|
||||||
|
* @param string[] $mapping Map of old to new classnames
|
||||||
|
*/
|
||||||
|
protected function updateLegacyClassNameField($dataClass, $fieldName, $mapping)
|
||||||
{
|
{
|
||||||
$schema = DataObject::getSchema();
|
$schema = DataObject::getSchema();
|
||||||
// Check first to ensure that the class has the specified field to update
|
// Check first to ensure that the class has the specified field to update
|
||||||
@ -426,36 +435,59 @@ class DatabaseAdmin extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load a list of any records that have obsolete class names
|
// Load a list of any records that have obsolete class names
|
||||||
$badRecordCount = DataObject::get($dataClass)
|
$table = $schema->tableName($dataClass);
|
||||||
->filter([$fieldName => $oldClassName])
|
$currentClassNameList = DB::query("SELECT DISTINCT(\"{$fieldName}\") FROM \"{$table}\"")->column();
|
||||||
->count();
|
|
||||||
|
|
||||||
if (!$badRecordCount) {
|
// Get all invalid classes for this field
|
||||||
|
$invalidClasses = array_intersect($currentClassNameList, array_keys($mapping));
|
||||||
|
if (!$invalidClasses) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Director::is_cli()) {
|
$numberClasses = count($invalidClasses);
|
||||||
echo " * Correcting {$badRecordCount} obsolete {$fieldName} values for {$newClassName}\n";
|
DB::alteration_message(
|
||||||
} else {
|
"Correcting obsolete {$fieldName} values for {$numberClasses} outdated types",
|
||||||
echo "<li>Correcting {$badRecordCount} obsolete {$fieldName} values for {$newClassName}</li>\n";
|
'obsolete'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Build case assignment based on all intersected legacy classnames
|
||||||
|
$cases = [];
|
||||||
|
$params = [];
|
||||||
|
foreach ($invalidClasses as $invalidClass) {
|
||||||
|
$cases[] = "WHEN \"{$fieldName}\" = ? THEN ?";
|
||||||
|
$params[] = $invalidClass;
|
||||||
|
$params[] = $mapping[$invalidClass];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach ($this->getClassTables($dataClass) as $table) {
|
||||||
|
$casesSQL = implode(' ', $cases);
|
||||||
|
$sql = "UPDATE \"{$table}\" SET \"{$fieldName}\" = CASE {$casesSQL} ELSE \"{$fieldName}\" END";
|
||||||
|
DB::prepared_query($sql, $params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get tables to update for this class
|
||||||
|
*
|
||||||
|
* @param string $dataClass
|
||||||
|
* @return Generator|string[]
|
||||||
|
*/
|
||||||
|
protected function getClassTables($dataClass)
|
||||||
|
{
|
||||||
|
$schema = DataObject::getSchema();
|
||||||
$table = $schema->tableName($dataClass);
|
$table = $schema->tableName($dataClass);
|
||||||
|
|
||||||
$updateQuery = "UPDATE \"{$table}%s\" SET \"{$fieldName}\" = ? WHERE \"{$fieldName}\" = ?";
|
// Base table
|
||||||
$updateQueries = [sprintf($updateQuery, '')];
|
yield $table;
|
||||||
|
|
||||||
// Remap versioned table class name values as well
|
// Remap versioned table class name values as well
|
||||||
/** @var Versioned|DataObject $class */
|
/** @var Versioned|DataObject $dataClass */
|
||||||
$class = DataObject::singleton($dataClass);
|
$dataClass = DataObject::singleton($dataClass);
|
||||||
if ($class->hasExtension(Versioned::class)) {
|
if ($dataClass->hasExtension(Versioned::class)) {
|
||||||
if ($class->hasStages()) {
|
if ($dataClass->hasStages()) {
|
||||||
$updateQueries[] = sprintf($updateQuery, '_Live');
|
yield "{$table}_Live";
|
||||||
}
|
}
|
||||||
$updateQueries[] = sprintf($updateQuery, '_Versions');
|
yield "{$table}_Versions";
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($updateQueries as $query) {
|
|
||||||
DB::prepared_query($query, [$newClassName, $oldClassName]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,4 +567,20 @@ class DatabaseAdmin extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate all class names
|
||||||
|
*
|
||||||
|
* @todo Migrate to separate build task
|
||||||
|
*/
|
||||||
|
protected function migrateClassNames()
|
||||||
|
{
|
||||||
|
$remappingConfig = $this->config()->get('classname_value_remapping');
|
||||||
|
$remappingFields = $this->getClassNameRemappingFields();
|
||||||
|
foreach ($remappingFields as $className => $fieldNames) {
|
||||||
|
foreach ($fieldNames as $fieldName) {
|
||||||
|
$this->updateLegacyClassNameField($className, $fieldName, $remappingConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user