From 156f63bce38a6b95d0f117eedbeb8819eb51d1b7 Mon Sep 17 00:00:00 2001 From: Christopher Joe Date: Mon, 6 Nov 2017 14:04:06 +1300 Subject: [PATCH] ENH shorten auto-generated table names Fix add check for legacy long table name and rename to short version --- src/ORM/DataObject.php | 21 +++++++++++++++++++++ src/ORM/DataObjectSchema.php | 30 +++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/ORM/DataObject.php b/src/ORM/DataObject.php index b236b253c96..ee7dd65ed41 100644 --- a/src/ORM/DataObject.php +++ b/src/ORM/DataObject.php @@ -3623,6 +3623,7 @@ public function requireTable() $fields = $schema->databaseFields(static::class, false); $indexes = $schema->databaseIndexes(static::class, false); $extensions = self::database_extensions(static::class); + $legacyTables = $schema->getLegacyTableNames(static::class); if (empty($table)) { throw new LogicException( @@ -3630,6 +3631,26 @@ public function requireTable() ); } + if ($legacyTables) { + $ignore = Config::inst()->get(static::class, 'ignored_legacy_tables') ?: []; + $renameTables = array_diff( + array_intersect($legacyTables, DB::table_list()), + $ignore + ); + if (count($renameTables) > 1) { + $class = static::class; + $legacyList = implode(', ', $renameTables); + trigger_error( + "Class $class has multiple legacy tables: $legacyList", + E_USER_NOTICE + ); + } + if (count($renameTables) === 1) { + $dbSchema = DB::get_schema(); + $dbSchema->renameTable($renameTables[0], $table); + } + } + if ($fields) { $hasAutoIncPK = get_parent_class($this ?? '') === self::class; DB::require_table( diff --git a/src/ORM/DataObjectSchema.php b/src/ORM/DataObjectSchema.php index dcd7ca17d7a..71aaaa430d1 100644 --- a/src/ORM/DataObjectSchema.php +++ b/src/ORM/DataObjectSchema.php @@ -318,18 +318,30 @@ protected function buildTableName($class) { $table = Config::inst()->get($class, 'table_name', Config::UNINHERITED); - // Generate default table name + // Return table name if configured if ($table) { return $table; } + // Use classname directly if not namespaced if (strpos($class ?? '', '\\') === false) { return $class; } - $separator = DataObjectSchema::config()->uninherited('table_namespace_separator'); - $table = str_replace('\\', $separator ?? '', trim($class ?? '', '\\')); + // Attempt to generate a nice table name + $separator = DataObjectSchema::config()->uninherited('table_namespace_separator') ?? ''; + $parts = explode('\\', trim($class ?? '', '\\')); + $vendor = array_slice($parts, 0, 1)[0]; + $base = array_slice($parts, -1, 1)[0]; + if ($vendor && $base && $vendor !== $base) { + $table = "{$vendor}{$separator}{$base}"; + } elseif ($base) { + $table = $base; + } else { + throw new InvalidArgumentException("Unable to build a table name for class '$class'. Define a table_name for this class."); + } + // Display a warning about namespaced classes producing long table names if (!ClassInfo::classImplements($class, TestOnly::class) && $this->classHasTable($class)) { DBSchemaManager::showTableNameWarning($table, $class); } @@ -337,6 +349,18 @@ protected function buildTableName($class) return $table; } + /** + * @param $class + * @return array + */ + public function getLegacyTableNames($class) + { + $separator = DataObjectSchema::config()->uninherited('table_namespace_separator'); + $names[] = str_replace('\\', $separator, trim($class, '\\')); + + return $names; + } + /** * Return the complete map of fields to specification on this object, including fixed_fields. * "ID" will be included on every table.