Revert "Add a new type of database to the installer from extension"
It caused a 20% latency regression by unconditionally parsing extension.json files on every single load instead of using the existing caching infrastructure. There are further problems with the use of parsing/loading extension.json files in a method that is incompatible with the existing architecture. This primarily reverts commit46eabe275c. Also needed to revert16381261aeand7c72347ec1. Bug: T258664 Change-Id: I34a783c3f0df0447876a26441bb2d12e02368871
This commit is contained in:
parent
d7a9cb7db3
commit
0b43c49465
16 changed files with 87 additions and 643 deletions
|
|
@ -821,29 +821,6 @@ class LocalisationCache {
|
|||
return $used;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $messagesDirs = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $additionalMessagesDirs = [];
|
||||
|
||||
/**
|
||||
* Add additional path for looking for i18n localization messages
|
||||
*
|
||||
* @internal for Installer with DbType extensions
|
||||
* @since 1.35
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
*/
|
||||
public function addMessagesDir( string $name, string $path ) : void {
|
||||
$this->additionalMessagesDirs[$name] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the combined list of messages dirs from
|
||||
* core and extensions
|
||||
|
|
@ -861,7 +838,7 @@ class LocalisationCache {
|
|||
'rest' => "$IP/includes/Rest/i18n",
|
||||
'oojs-ui' => "$IP/resources/lib/ooui/i18n",
|
||||
'paramvalidator' => "$IP/includes/libs/ParamValidator/i18n",
|
||||
] + $this->options->get( 'MessagesDirs' ) + $this->additionalMessagesDirs;
|
||||
] + $this->options->get( 'MessagesDirs' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
* @file
|
||||
* @ingroup Installer
|
||||
*/
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Wikimedia\Rdbms\IDatabase;
|
||||
use Wikimedia\Rdbms\IMaintainableDatabase;
|
||||
|
|
@ -198,8 +197,8 @@ abstract class DatabaseUpdater {
|
|||
Maintenance $maintenance = null
|
||||
) {
|
||||
$type = $db->getType();
|
||||
if ( InstallerDBSupport::getInstance()->hasDatabase( $type ) ) {
|
||||
$class = InstallerDBSupport::getInstance()->getDBUpdaterClass( $type );
|
||||
if ( in_array( $type, Installer::getDBTypes() ) ) {
|
||||
$class = ucfirst( $type ) . 'Updater';
|
||||
|
||||
return new $class( $db, $shared, $maintenance );
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
* @ingroup Installer
|
||||
*/
|
||||
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use MediaWiki\Interwiki\NullInterwikiLookup;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MediaWiki\Shell\Shell;
|
||||
|
|
@ -101,9 +100,19 @@ abstract class Installer {
|
|||
protected $parserOptions;
|
||||
|
||||
/**
|
||||
* @var InstallerDBSupport
|
||||
* Known database types. These correspond to the class names <type>Installer,
|
||||
* and are also MediaWiki database types valid for $wgDBtype.
|
||||
*
|
||||
* To add a new type, create a <type>Installer class and a Database<type>
|
||||
* class, and add a config-type-<type> message to MessagesEn.php.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $installerDbSupport;
|
||||
protected static $dbTypes = [
|
||||
'mysql',
|
||||
'postgres',
|
||||
'sqlite',
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of environment check methods called by doEnvironmentChecks().
|
||||
|
|
@ -397,6 +406,7 @@ abstract class Installer {
|
|||
*/
|
||||
public function __construct() {
|
||||
global $wgMemc, $wgUser, $wgObjectCaches;
|
||||
|
||||
$defaultConfig = new GlobalVarConfig(); // all the stuff from DefaultSettings.php
|
||||
$installerConfig = self::getInstallerConfig( $defaultConfig );
|
||||
|
||||
|
|
@ -448,9 +458,7 @@ abstract class Installer {
|
|||
$this->doEnvironmentPreps();
|
||||
|
||||
$this->compiledDBs = [];
|
||||
$this->installerDbSupport = InstallerDBSupport::getInstance();
|
||||
|
||||
foreach ( $this->installerDbSupport->getDatabases() as $type ) {
|
||||
foreach ( self::getDBTypes() as $type ) {
|
||||
$installer = $this->getDBInstaller( $type );
|
||||
|
||||
if ( !$installer->isCompiled() ) {
|
||||
|
|
@ -467,13 +475,11 @@ abstract class Installer {
|
|||
|
||||
/**
|
||||
* Get a list of known DB types.
|
||||
* @deprecated since 1.35 use InstallerDBSupport::getDatabases instead
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getDBTypes() {
|
||||
wfDeprecated( __METHOD__, '1.35' );
|
||||
return InstallerDBSupport::getInstance()->getDatabases();
|
||||
return self::$dbTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -555,16 +561,13 @@ abstract class Installer {
|
|||
|
||||
/**
|
||||
* Get the DatabaseInstaller class name for this type
|
||||
* @deprecated since 1.35 use InstallerDBSupport instead
|
||||
*
|
||||
* @param string $type database type ($wgDBtype)
|
||||
* @return string Class name
|
||||
* @since 1.30
|
||||
*/
|
||||
public static function getDBInstallerClass( $type ) {
|
||||
wfDeprecated( __METHOD__, '1.35' );
|
||||
|
||||
return InstallerDBSupport::getInstance()->getDBInstallerClass( $type );
|
||||
return ucfirst( $type ) . 'Installer';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -579,8 +582,10 @@ abstract class Installer {
|
|||
$type = $this->getVar( 'wgDBtype' );
|
||||
}
|
||||
|
||||
$type = strtolower( $type );
|
||||
|
||||
if ( !isset( $this->dbInstallers[$type] ) ) {
|
||||
$class = $this->installerDbSupport->getDBInstallerClass( $type );
|
||||
$class = self::getDBInstallerClass( $type );
|
||||
$this->dbInstallers[$type] = new $class( $this );
|
||||
}
|
||||
|
||||
|
|
@ -764,7 +769,7 @@ abstract class Installer {
|
|||
$allNames = [];
|
||||
|
||||
// Messages: config-type-mysql, config-type-postgres, config-type-sqlite
|
||||
foreach ( $this->installerDbSupport->getDatabases() as $name ) {
|
||||
foreach ( self::getDBTypes() as $name ) {
|
||||
$allNames[] = wfMessage( "config-type-$name" )->text();
|
||||
}
|
||||
|
||||
|
|
@ -1862,18 +1867,4 @@ abstract class Installer {
|
|||
set_time_limit( 0 );
|
||||
Wikimedia\restoreWarnings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the extension selected to provide the database or null
|
||||
* if the database is provided by core.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUsedExtensionName() : ?string {
|
||||
if ( empty( $this->settings['wgDBtype'] ) ) {
|
||||
return null;
|
||||
}
|
||||
return $this->installerDbSupport
|
||||
->getExtensionNameForDatabase( $this->settings['wgDBtype'] );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,336 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
* @ingroup Installer
|
||||
*
|
||||
* @author Art Baltai
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
namespace MediaWiki\Installer\Services;
|
||||
|
||||
use DatabaseInstaller;
|
||||
use DatabaseUpdater;
|
||||
use InvalidArgumentException;
|
||||
use MediaWiki\Logger\LoggerFactory;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use MysqlInstaller;
|
||||
use MysqlUpdater;
|
||||
use PostgresInstaller;
|
||||
use PostgresUpdater;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SqliteInstaller;
|
||||
use SqliteUpdater;
|
||||
use Wikimedia\Rdbms\Database;
|
||||
use Wikimedia\Rdbms\DatabaseMysqli;
|
||||
use Wikimedia\Rdbms\DatabasePostgres;
|
||||
use Wikimedia\Rdbms\DatabaseSqlite;
|
||||
|
||||
/**
|
||||
* @since 1.35
|
||||
*/
|
||||
class InstallerDBSupport {
|
||||
public const EXTENSION_TYPE_DATABASE = 'database';
|
||||
|
||||
/**
|
||||
* @var InstallerDBSupport $instance
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Known database types. These correspond to the class names <type>Installer,
|
||||
* and are also MediaWiki database types valid for $wgDBtype.
|
||||
*
|
||||
* To add a new type, create a <type>Installer class and a Database<type>
|
||||
* class, and add a config-type-<type> message to MessagesEn.php.
|
||||
*
|
||||
* @var array<string, array>
|
||||
*/
|
||||
private $databaseInfo = [
|
||||
'mysql' => [
|
||||
'installer' => MysqlInstaller::class,
|
||||
'updater' => MysqlUpdater::class,
|
||||
'driver' => DatabaseMysqli::class,
|
||||
'extension' => null
|
||||
],
|
||||
'postgres' => [
|
||||
'installer' => PostgresInstaller::class,
|
||||
'updater' => PostgresUpdater::class,
|
||||
'driver' => DatabasePostgres::class,
|
||||
'extension' => null
|
||||
],
|
||||
'sqlite' => [
|
||||
'installer' => SqliteInstaller::class,
|
||||
'updater' => SqliteUpdater::class,
|
||||
'driver' => DatabaseSqlite::class,
|
||||
'extension' => null
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* @var InstallerExtensionRegistration
|
||||
*/
|
||||
private $extensionRegistration;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public static function getInstance(): self {
|
||||
global $IP, $wgExtensionDirectory;
|
||||
if ( !isset( self::$instance ) ) {
|
||||
$extensionDir = $wgExtensionDirectory ?: "$IP/extensions";
|
||||
$installerRegistration = new InstallerExtensionRegistration(
|
||||
$extensionDir,
|
||||
MediaWikiServices::getInstance()->getLocalisationCache()
|
||||
);
|
||||
self::$instance = new InstallerDBSupport(
|
||||
$installerRegistration,
|
||||
LoggerFactory::getInstance( 'Installer' )
|
||||
);
|
||||
self::$instance->registerDbExtensions(
|
||||
( new InstallerExtensionSelector( $extensionDir ) )
|
||||
->getExtOptionsByType( self::EXTENSION_TYPE_DATABASE )
|
||||
);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
private function __construct(
|
||||
InstallerExtensionRegistration $extensionRegistration,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->extensionRegistration = $extensionRegistration;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
private function registerDbExtensions( iterable $extDbOptionsByType ): bool {
|
||||
$registered = false;
|
||||
foreach ( $extDbOptionsByType as $extensionName => $extDbOptions ) {
|
||||
$result = $this->registerDbExtension(
|
||||
$extensionName,
|
||||
$extDbOptions
|
||||
);
|
||||
$registered = $result || $registered;
|
||||
}
|
||||
|
||||
return $registered;
|
||||
}
|
||||
|
||||
private function registerDbExtension(
|
||||
string $extensionName,
|
||||
array $extJsonOptions
|
||||
): bool {
|
||||
if ( !isset( $extJsonOptions['Providers']['Databases'] ) ) {
|
||||
return false;
|
||||
}
|
||||
$newDatabases = $extJsonOptions['Providers']['Databases'];
|
||||
$isRegistred = false;
|
||||
foreach ( $newDatabases as $database => $options ) {
|
||||
if ( is_numeric( $database ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( $isRegistred === false ) {
|
||||
$this->extensionRegistration->register(
|
||||
$extensionName,
|
||||
$extJsonOptions
|
||||
);
|
||||
$isRegistred = true;
|
||||
}
|
||||
|
||||
$this->registerDatabase(
|
||||
$database,
|
||||
$options['Installer'] ?? $this->getInstallerClassAuto( $database ),
|
||||
$options['Updater'] ?? $this->getUpdaterClassAuto( $database ),
|
||||
$options['Driver'] ?? $this->getDriverClassAuto( $database ),
|
||||
$extensionName
|
||||
);
|
||||
}
|
||||
|
||||
return $isRegistred;
|
||||
}
|
||||
|
||||
private function isDatabaseInfoValid(
|
||||
string $dbInstaller,
|
||||
string $dbUpdater,
|
||||
string $dbDriver
|
||||
): bool {
|
||||
$isValid = true;
|
||||
if ( !is_subclass_of( $dbInstaller, DatabaseInstaller::class ) ) {
|
||||
$this->logger->warning( 'Database `Installer` should be a subclass of '
|
||||
. DatabaseInstaller::class );
|
||||
$isValid = false;
|
||||
}
|
||||
|
||||
if ( !is_subclass_of( $dbUpdater, DatabaseUpdater::class ) ) {
|
||||
$this->logger->warning( 'Database `Updater` should be a subclass of '
|
||||
. DatabaseUpdater::class );
|
||||
$isValid = false;
|
||||
}
|
||||
|
||||
if ( !is_subclass_of( $dbDriver, Database::class ) ) {
|
||||
$this->logger->warning( 'Database `Driver` should be a subclass of ' . Database::class );
|
||||
$isValid = false;
|
||||
}
|
||||
return $isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $database
|
||||
* @param string $dbInstaller
|
||||
* @param string $dbUpdater
|
||||
* @param string $dbDriver
|
||||
* @param string $extensionName
|
||||
*/
|
||||
private function registerDatabase(
|
||||
string $database,
|
||||
string $dbInstaller,
|
||||
string $dbUpdater,
|
||||
string $dbDriver,
|
||||
string $extensionName
|
||||
): void {
|
||||
if ( !$this->isDatabaseInfoValid( $dbInstaller, $dbUpdater, $dbDriver ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->databaseInfo[ strtolower( $database ) ] = [
|
||||
'installer' => $dbInstaller,
|
||||
'updater' => $dbUpdater,
|
||||
'driver' => $dbDriver,
|
||||
'extension' => $extensionName,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of known DB types.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getDatabases(): array {
|
||||
return array_keys( $this->databaseInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks wheather given database type is registered
|
||||
* @param string $database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasDatabase( string $database ): bool {
|
||||
return array_key_exists( $database, $this->databaseInfo );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database installer class for given database type, throws an
|
||||
* InvalidArgumentException if no given database registerred
|
||||
*
|
||||
* @param string $database
|
||||
* @return string Class name
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getDBInstallerClass( string $database ): string {
|
||||
if ( !isset( $this->databaseInfo[strtolower( $database )] ) ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" no registered database found for type '$database'" );
|
||||
}
|
||||
return $this->databaseInfo[strtolower( $database )]['installer'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database updater class for given database type, throws an
|
||||
* InvalidArgumentException if no given database registerred
|
||||
*
|
||||
* @param string $database
|
||||
* @return string class name
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getDBUpdaterClass( string $database ): string {
|
||||
if ( !isset( $this->databaseInfo[strtolower( $database )] ) ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" no registered database found for type '$database'" );
|
||||
}
|
||||
return $this->databaseInfo[strtolower( $database )]['updater'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database driver class for given database type, throws an
|
||||
* InvalidArgumentException if no given database registerred
|
||||
*
|
||||
* @param string $database
|
||||
* @return string class name
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getDBDriverClass( string $database ): string {
|
||||
if ( !isset( $this->databaseInfo[strtolower( $database )] ) ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" no registered database found for type '$database'" );
|
||||
}
|
||||
return $this->databaseInfo[strtolower( $database )]['driver'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extension name that implements classes for given database type, throws an
|
||||
* InvalidArgumentException if no given database registerred
|
||||
*
|
||||
* @param string $database
|
||||
* @return string|null
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getExtensionNameForDatabase(
|
||||
string $database
|
||||
): ?string {
|
||||
if ( !isset( $this->databaseInfo[strtolower( $database )] ) ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" no registered database found for type '$database'" );
|
||||
}
|
||||
return $this->databaseInfo[strtolower( $database )]['extension'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate default name for database Installer
|
||||
*
|
||||
* @param string $type database type ($wgDBtype)
|
||||
* @return string Class name
|
||||
*/
|
||||
private function getInstallerClassAuto( string $type ): string {
|
||||
return ucfirst( $type ) . 'Installer';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate default name for database Updater
|
||||
*
|
||||
* @param string $type database type ($wgDBtype)
|
||||
* @return string Class name
|
||||
*/
|
||||
private function getUpdaterClassAuto( string $type ): string {
|
||||
return ucfirst( $type ) . 'Updater';
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate default name for database Driver
|
||||
*
|
||||
* @param string $type database type ($wgDBtype)
|
||||
* @return string Class name
|
||||
*/
|
||||
private function getDriverClassAuto( string $type ): string {
|
||||
return 'Database' . ucfirst( $type );
|
||||
}
|
||||
}
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
* @ingroup Installer
|
||||
*
|
||||
* @author Art Baltai
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
namespace MediaWiki\Installer\Services;
|
||||
|
||||
use ExtensionRegistry;
|
||||
use LocalisationCache;
|
||||
|
||||
/**
|
||||
* @since 1.35
|
||||
*/
|
||||
class InstallerExtensionRegistration {
|
||||
|
||||
/** @var string */
|
||||
private $extensionDir;
|
||||
|
||||
/** @var LocalisationCache */
|
||||
private $localisationCache;
|
||||
|
||||
public function __construct( string $extensionDir, LocalisationCache $localisationCache ) {
|
||||
$this->extensionDir = $extensionDir;
|
||||
$this->localisationCache = $localisationCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register class autoloader, i18n messages
|
||||
* @param string $extensionName
|
||||
* @param array $extJsonOptions
|
||||
*/
|
||||
public function register(
|
||||
string $extensionName,
|
||||
array $extJsonOptions
|
||||
): void {
|
||||
$this->registerClassAutoloader( $extensionName, $extJsonOptions );
|
||||
$this->registerMessagesDirs( $extensionName, $extJsonOptions );
|
||||
}
|
||||
|
||||
public function registerClassAutoloader(
|
||||
string $extensionName,
|
||||
array $extJsonOptions
|
||||
): void {
|
||||
global $wgAutoloadLocalClasses;
|
||||
|
||||
$extPath = $this->getExtensionPath( $extensionName );
|
||||
ExtensionRegistry::exportAutoloadClassesAndNamespaces(
|
||||
$extPath,
|
||||
$extJsonOptions
|
||||
);
|
||||
// important for upgrade (mw-config/?page=ExistingWiki) with existing LocalSettings.php
|
||||
if (
|
||||
!empty( $extJsonOptions['AutoloadClasses'] )
|
||||
&& is_array( $extJsonOptions['AutoloadClasses'] )
|
||||
) {
|
||||
foreach ( $extJsonOptions['AutoloadClasses'] as $className => $fileName ) {
|
||||
$wgAutoloadLocalClasses[$className] = "$extPath/$fileName";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function registerMessagesDirs(
|
||||
string $extensionName,
|
||||
array $extJsonOptions
|
||||
): void {
|
||||
if ( !is_array( $extJsonOptions['MessagesDirs'] ?? null ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $extJsonOptions['MessagesDirs'] as $messageType => $messagesDirs ) {
|
||||
$messagesDirs = (array)$messagesDirs;
|
||||
foreach ( $messagesDirs as $key => $messageDir ) {
|
||||
$i18nDir = $this->getExtensionPath( $extensionName ) . "/$messageDir";
|
||||
if ( !is_dir( $i18nDir ) ) {
|
||||
continue;
|
||||
}
|
||||
$this->localisationCache->addMessagesDir(
|
||||
count( $messagesDirs ) === 1
|
||||
? $messageType
|
||||
: "{$messageType}_{$key}",
|
||||
$i18nDir
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getExtensionPath( string $extensionName ) : string {
|
||||
return "{$this->extensionDir}/{$extensionName}";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*
|
||||
* @file
|
||||
* @ingroup Installer
|
||||
*
|
||||
* @author Art Baltai
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
namespace MediaWiki\Installer\Services;
|
||||
|
||||
use Generator;
|
||||
|
||||
/**
|
||||
* @since 1.35
|
||||
*/
|
||||
class InstallerExtensionSelector {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $extensionDir;
|
||||
|
||||
/**
|
||||
* @var string[]|null
|
||||
*/
|
||||
private $extensionJsonPath;
|
||||
|
||||
public function __construct( string $extensionDir ) {
|
||||
$this->extensionDir = $extensionDir;
|
||||
}
|
||||
|
||||
private function getExtensionJsonPaths() : array {
|
||||
if ( $this->extensionJsonPath === null ) {
|
||||
$this->extensionJsonPath = [];
|
||||
if ( is_dir( $this->extensionDir ) ) {
|
||||
$dh = opendir( $this->extensionDir );
|
||||
while ( ( $extension = readdir( $dh ) ) !== false ) {
|
||||
if ( mb_substr( $extension, 0, 1 ) === '.' ) {
|
||||
continue;
|
||||
}
|
||||
$jsonPath = "{$this->extensionDir}/{$extension}/extension.json";
|
||||
if ( is_file( $jsonPath ) && is_readable( $jsonPath ) ) {
|
||||
$this->extensionJsonPath[$extension] = $jsonPath;
|
||||
}
|
||||
}
|
||||
closedir( $dh );
|
||||
|
||||
uksort( $this->extensionJsonPath, 'strnatcasecmp' );
|
||||
} // @todo else:warning?
|
||||
}
|
||||
|
||||
return $this->extensionJsonPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Generator for interating through all exntension.json files converterd
|
||||
* into array. Key is string of exntension name and value is decoded exntension.json.
|
||||
*
|
||||
* @return Generator
|
||||
*/
|
||||
private function getExtensionJsons() : Generator {
|
||||
foreach ( $this->getExtensionJsonPaths() as $extension => $jsonPath ) {
|
||||
$json = file_get_contents( $jsonPath );
|
||||
$options = json_decode( $json, true );
|
||||
if ( !is_array( $options ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $extension => $options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Generator for interating through extension's options
|
||||
* filtered by certain type.
|
||||
*
|
||||
* @param string $type
|
||||
* @return Generator
|
||||
*/
|
||||
public function getExtOptionsByType( string $type ) : Generator {
|
||||
foreach ( $this->getExtensionJsons() as $extensionName => $options ) {
|
||||
if ( $type === ( $options['type'] ?? null ) ) {
|
||||
yield $extensionName => $options;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
* @file
|
||||
* @ingroup Installer
|
||||
*/
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
|
||||
class WebInstallerDBConnect extends WebInstallerPage {
|
||||
|
||||
|
|
@ -51,7 +50,7 @@ class WebInstallerDBConnect extends WebInstallerPage {
|
|||
|
||||
// Messages: config-dbsupport-mysql, config-dbsupport-postgres, config-dbsupport-sqlite
|
||||
$dbSupport = '';
|
||||
foreach ( InstallerDBSupport::getInstance()->getDatabases() as $type ) {
|
||||
foreach ( Installer::getDBTypes() as $type ) {
|
||||
$dbSupport .= wfMessage( "config-dbsupport-$type" )->plain() . "\n";
|
||||
}
|
||||
$this->addHTML( $this->parent->getInfoBox(
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@
|
|||
* @ingroup Installer
|
||||
*/
|
||||
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
|
||||
class WebInstallerExistingWiki extends WebInstallerPage {
|
||||
|
||||
/**
|
||||
|
|
@ -142,7 +140,7 @@ class WebInstallerExistingWiki extends WebInstallerPage {
|
|||
protected function handleExistingUpgrade( $vars ) {
|
||||
// Check $wgDBtype
|
||||
if ( !isset( $vars['wgDBtype'] ) ||
|
||||
!InstallerDBSupport::getInstance()->hasDatabase( $vars['wgDBtype'] )
|
||||
!in_array( $vars['wgDBtype'], Installer::getDBTypes() )
|
||||
) {
|
||||
return Status::newFatal( 'config-localsettings-connection-error', '' );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
* @ingroup Installer
|
||||
*/
|
||||
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use Wikimedia\IPUtils;
|
||||
|
||||
class WebInstallerOptions extends WebInstallerPage {
|
||||
|
|
@ -148,14 +147,7 @@ class WebInstallerOptions extends WebInstallerPage {
|
|||
$this->getFieldsetEnd();
|
||||
$this->addHTML( $skinHtml );
|
||||
|
||||
$extensions = array_filter(
|
||||
$this->parent->findExtensions()->value,
|
||||
function ( $extensionInfo ) {
|
||||
return ( $extensionInfo['type'] ?? null )
|
||||
!== InstallerDBSupport::EXTENSION_TYPE_DATABASE;
|
||||
}
|
||||
);
|
||||
|
||||
$extensions = $this->parent->findExtensions()->value;
|
||||
'@phan-var array[] $extensions';
|
||||
$dependencyMap = [];
|
||||
|
||||
|
|
@ -190,7 +182,7 @@ class WebInstallerOptions extends WebInstallerPage {
|
|||
'class' => 'config-ext-input'
|
||||
];
|
||||
$labelAttribs = [];
|
||||
|
||||
$fullDepList = [];
|
||||
if ( isset( $info['requires']['extensions'] ) ) {
|
||||
$dependencyMap[$ext]['extensions'] = $info['requires']['extensions'];
|
||||
$labelAttribs['class'] = 'mw-ext-with-dependencies';
|
||||
|
|
@ -545,10 +537,6 @@ class WebInstallerOptions extends WebInstallerPage {
|
|||
$extsToInstall[] = $ext;
|
||||
}
|
||||
}
|
||||
$dbext = $this->parent->getUsedExtensionName();
|
||||
if ( $dbext ) {
|
||||
$extsToInstall[] = $dbext;
|
||||
}
|
||||
$this->parent->setVar( '_Extensions', $extsToInstall );
|
||||
|
||||
if ( $this->getVar( '_MainCacheType' ) == 'memcached' ) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ use Exception;
|
|||
use HashBagOStuff;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
|
@ -395,7 +394,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
* @since 1.18
|
||||
*/
|
||||
final public static function factory( $type, $params = [], $connect = self::NEW_CONNECTED ) {
|
||||
$class = InstallerDBSupport::getInstance()->getDBDriverClass( $type );
|
||||
$class = self::getClass( $type, $params['driver'] ?? null );
|
||||
|
||||
if ( class_exists( $class ) && is_subclass_of( $class, IDatabase::class ) ) {
|
||||
$params += [
|
||||
|
|
@ -456,11 +455,64 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
|
|||
self::ATTR_SCHEMAS_AS_TABLE_GROUPS => false
|
||||
];
|
||||
|
||||
$class = InstallerDBSupport::getInstance()->getDBDriverClass( $dbType );
|
||||
$class = self::getClass( $dbType, $driver );
|
||||
|
||||
return call_user_func( [ $class, 'getAttributes' ] ) + $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dbType A possible DB type (sqlite, mysql, postgres,...)
|
||||
* @param string|null $driver Optional name of a specific DB client driver
|
||||
* @return string Database subclass name to use
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private static function getClass( $dbType, $driver = null ) {
|
||||
// For database types with built-in support, the below maps type to IDatabase
|
||||
// implementations. For types with multiple 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<Type>" us used, eg. DatabaseFoo for type 'foo'.
|
||||
static $builtinTypes = [
|
||||
'mysql' => [ 'mysqli' => DatabaseMysqli::class ],
|
||||
'sqlite' => DatabaseSqlite::class,
|
||||
'postgres' => DatabasePostgres::class,
|
||||
];
|
||||
|
||||
$dbType = strtolower( $dbType );
|
||||
$class = false;
|
||||
|
||||
if ( isset( $builtinTypes[$dbType] ) ) {
|
||||
$possibleDrivers = $builtinTypes[$dbType];
|
||||
if ( is_string( $possibleDrivers ) ) {
|
||||
$class = $possibleDrivers;
|
||||
} elseif ( (string)$driver !== '' ) {
|
||||
if ( !isset( $possibleDrivers[$driver] ) ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" type '$dbType' does not support driver '{$driver}'" );
|
||||
}
|
||||
|
||||
$class = $possibleDrivers[$driver];
|
||||
} else {
|
||||
foreach ( $possibleDrivers as $posDriver => $possibleClass ) {
|
||||
if ( extension_loaded( $posDriver ) ) {
|
||||
$class = $possibleClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$class = 'Database' . ucfirst( $dbType );
|
||||
}
|
||||
|
||||
if ( $class === false ) {
|
||||
throw new InvalidArgumentException( __METHOD__ .
|
||||
" no viable database extension found for type '$dbType'" );
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @stable to override
|
||||
* @return array Map of (Database::ATTR_* constant => value)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
*/
|
||||
|
||||
use MediaWiki\ExtensionInfo;
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
|
||||
/**
|
||||
|
|
@ -417,8 +416,6 @@ class SpecialVersion extends SpecialPage {
|
|||
'antispam' => wfMessage( 'version-antispam' )->text(),
|
||||
'skin' => wfMessage( 'version-skins' )->text(),
|
||||
'api' => wfMessage( 'version-api' )->text(),
|
||||
InstallerDBSupport::EXTENSION_TYPE_DATABASE =>
|
||||
wfMessage( 'version-database' )->text(),
|
||||
'other' => wfMessage( 'version-other' )->text(),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -3603,7 +3603,6 @@
|
|||
"version-variables": "Variables",
|
||||
"version-editors": "Editors",
|
||||
"version-antispam": "Spam prevention",
|
||||
"version-database": "Custom database support",
|
||||
"version-api": "API",
|
||||
"version-other": "Other",
|
||||
"version-mediahandlers": "Media handlers",
|
||||
|
|
|
|||
|
|
@ -3819,7 +3819,6 @@
|
|||
"version-variables": "{{Identical|Variable}}",
|
||||
"version-editors": "Part of [[Special:Version]].\nThis message is followed by the list of installed extensions that provide an editor or enhance editing functionality.\n{{Identical|Editor}}",
|
||||
"version-antispam": "Part of [[Special:Version]].\nThis message is followed by the list of SPAM prevention extensions.",
|
||||
"version-database": "Database type",
|
||||
"version-api": "{{optional}}",
|
||||
"version-other": "{{Identical|Other}}",
|
||||
"version-mediahandlers": "Used in [[Special:Version]]. It is the title of a section for media handler extensions (e.g. [[mw:Extension:OggHandler]]).\nThere are no such extensions here, so look at [[wikipedia:Special:Version]] for an example.",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
require_once __DIR__ . '/Maintenance.php';
|
||||
|
||||
use MediaWiki\Installer\Services\InstallerDBSupport;
|
||||
use MediaWiki\MediaWikiServices;
|
||||
use Wikimedia\Rdbms\DatabaseSqlite;
|
||||
|
||||
|
|
@ -142,9 +141,8 @@ class UpdateMediaWiki extends Maintenance {
|
|||
$db = $this->getDB( DB_MASTER );
|
||||
|
||||
# Check to see whether the database server meets the minimum requirements
|
||||
/** @var string|DatabaseInstaller $dbInstallerClass */
|
||||
$dbInstallerClass = InstallerDBSupport::getInstance()
|
||||
->getDBInstallerClass( $db->getType() );
|
||||
/** @var DatabaseInstaller $dbInstallerClass */
|
||||
$dbInstallerClass = Installer::getDBInstallerClass( $db->getType() );
|
||||
$status = $dbInstallerClass::meetsMinimumRequirement( $db->getServerVersion() );
|
||||
if ( !$status->isOK() ) {
|
||||
// This might output some wikitext like <strong> but it should be comprehensible
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ class DatabaseTest extends PHPUnit\Framework\TestCase {
|
|||
$m = Database::NEW_UNCONNECTED; // no-connect mode
|
||||
$p = [ 'host' => 'localhost', 'user' => 'me', 'password' => 'myself', 'dbname' => 'i' ];
|
||||
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'mysql', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySql', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySQL', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'mysqli', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySqli', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabaseMysqli::class, Database::factory( 'MySQLi', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'postgres', $p, $m ) );
|
||||
$this->assertInstanceOf( DatabasePostgres::class, Database::factory( 'Postgres', $p, $m ) );
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,6 @@
|
|||
<testsuite name="languages">
|
||||
<directory>languages</directory>
|
||||
</testsuite>
|
||||
<testsuite name="rdbms">
|
||||
<directory>includes/libs/rdbms</directory>
|
||||
</testsuite>
|
||||
<testsuite name="parsertests">
|
||||
<file>suites/CoreParserTestSuite.php</file>
|
||||
<file>suites/ExtensionsParserTestSuite.php</file>
|
||||
|
|
|
|||
Loading…
Reference in a new issue