From 76e8d9762581f0564b7400503fdf20fb04df6352 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Wed, 24 Jan 2018 11:33:37 -0800 Subject: [PATCH] rdbms: Simplify Database::factory() Follows-up 0ff2b7a776 (T120333) which removed support for the deprecated php 'mysql' extension. It surprised me that the 'DatabaseMysql' entry could safely be removed from $classAliases. This was because the key is not direct input, but based on $canonicalDBTypes, which maps mysql to mysqli. Take this further by removing the indirection between type, driver and class name. * Map built-in db types directly to their class and driver. * Change fallback to assign $class directly from $dbType, without indirection of a $driver variable. * Remove unused $classAliases. Change-Id: I1200b07f66f23624410d848b6f382cb2dafa5c59 --- includes/libs/rdbms/database/Database.php | 64 +++++++++++------------ 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index 323c147824..1efa9a1f2e 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -336,53 +336,51 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * @since 1.18 */ final public static function factory( $dbType, $p = [] ) { - static $canonicalDBTypes = [ - 'mysql' => [ 'mysqli' ], - 'postgres' => [], - 'sqlite' => [], - 'oracle' => [], - 'mssql' => [], - ]; - static $classAliases = [ - 'DatabaseMssql' => DatabaseMssql::class, - 'DatabaseMysqli' => DatabaseMysqli::class, - 'DatabaseSqlite' => DatabaseSqlite::class, - 'DatabasePostgres' => DatabasePostgres::class + // For database types with built-in support, the below maps type to IDatabase + // implementations. For types with multipe driver implementations (PHP extensions), + // an array can be used, keyed by extension name. In case of an array, the + // optional 'driver' parameter can be used to force a specific driver. Otherwise, + // we auto-detect the first available driver. For types without built-in support, + // an class named "Database" us used, eg. DatabaseFoo for type 'foo'. + static $builtinTypes = [ + 'mssql' => DatabaseMssql::class, + 'mysql' => [ 'mysqli' => DatabaseMysqli::class ], + 'sqlite' => DatabaseSqlite::class, + 'postgres' => DatabasePostgres::class, ]; - $driver = false; $dbType = strtolower( $dbType ); - if ( isset( $canonicalDBTypes[$dbType] ) && $canonicalDBTypes[$dbType] ) { - $possibleDrivers = $canonicalDBTypes[$dbType]; - if ( !empty( $p['driver'] ) ) { - if ( in_array( $p['driver'], $possibleDrivers ) ) { - $driver = $p['driver']; - } else { - throw new InvalidArgumentException( __METHOD__ . - " type '$dbType' does not support driver '{$p['driver']}'" ); - } + $class = false; + if ( isset( $builtinTypes[$dbType] ) ) { + $possibleDrivers = $builtinTypes[$dbType]; + if ( is_string( $possibleDrivers ) ) { + $class = $possibleDrivers; } else { - foreach ( $possibleDrivers as $posDriver ) { - if ( extension_loaded( $posDriver ) ) { - $driver = $posDriver; - break; + if ( !empty( $p['driver'] ) ) { + if ( !isset( $possibleDrivers[$p['driver']] ) ) { + throw new InvalidArgumentException( __METHOD__ . + " type '$dbType' does not support driver '{$p['driver']}'" ); + } else { + $class = $possibleDrivers[$p['driver']]; + } + } else { + foreach ( $possibleDrivers as $posDriver => $possibleClass ) { + if ( extension_loaded( $posDriver ) ) { + $class = $possibleClass; + break; + } } } } } else { - $driver = $dbType; + $class = 'Database' . ucfirst( $dbType ); } - if ( $driver === false || $driver === '' ) { + if ( $class === false ) { throw new InvalidArgumentException( __METHOD__ . " no viable database extension found for type '$dbType'" ); } - $class = 'Database' . ucfirst( $driver ); - if ( isset( $classAliases[$class] ) ) { - $class = $classAliases[$class]; - } - if ( class_exists( $class ) && is_subclass_of( $class, IDatabase::class ) ) { // Resolve some defaults for b/c $p['host'] = isset( $p['host'] ) ? $p['host'] : false; -- 2.20.1