X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=blobdiff_plain;f=includes%2Finstaller%2FInstaller.php;h=abf4de4f692b92a3fa13071fc0efd93919b50a36;hp=f5e12d64775a25c9750c37978001c4a3a328ea36;hb=49aa4d3f9c48bced2e7293925786479a99b56b33;hpb=9f026c24ec2f1e2b4374c77b42b6547f55848872 diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php index f5e12d6477..abf4de4f69 100644 --- a/includes/installer/Installer.php +++ b/includes/installer/Installer.php @@ -23,7 +23,10 @@ * @file * @ingroup Deployment */ + +use MediaWiki\Interwiki\NullInterwikiLookup; use MediaWiki\MediaWikiServices; +use MediaWiki\Shell\Shell; /** * This documentation group collects source code files with deployment functionality. @@ -403,7 +406,7 @@ abstract class Installer { $installerConfig = self::getInstallerConfig( $defaultConfig ); // Reset all services and inject config overrides - MediaWiki\MediaWikiServices::resetGlobalInstance( $installerConfig ); + MediaWikiServices::resetGlobalInstance( $installerConfig ); // Don't attempt to load user language options (T126177) // This will be overridden in the web installer with the user-specified language @@ -414,13 +417,19 @@ abstract class Installer { Language::getLocalisationCache()->disableBackend(); // Disable all global services, since we don't have any configuration yet! - MediaWiki\MediaWikiServices::disableStorageBackend(); + MediaWikiServices::disableStorageBackend(); + $mwServices = MediaWikiServices::getInstance(); // Disable object cache (otherwise CACHE_ANYTHING will try CACHE_DB and // SqlBagOStuff will then throw since we just disabled wfGetDB) - $wgObjectCaches = MediaWikiServices::getInstance()->getMainConfig()->get( 'ObjectCaches' ); + $wgObjectCaches = $mwServices->getMainConfig()->get( 'ObjectCaches' ); $wgMemc = ObjectCache::getInstance( CACHE_NONE ); + // Disable interwiki lookup, to avoid database access during parses + $mwServices->redefineService( 'InterwikiLookup', function () { + return new NullInterwikiLookup(); + } ); + // Having a user with id = 0 safeguards us from DB access via User::loadOptions(). $wgUser = User::newFromId( 0 ); RequestContext::getMain()->setUser( $wgUser ); @@ -989,18 +998,22 @@ abstract class Installer { return true; } + if ( Shell::isDisabled() ) { + return true; + } + # Get a list of available locales. - $ret = false; - $lines = wfShellExec( '/usr/bin/locale -a', $ret ); + $result = Shell::command( '/usr/bin/locale', '-a' ) + ->execute(); - if ( $ret ) { + if ( $result->getExitCode() != 0 ) { return true; } + $lines = $result->getStdout(); $lines = array_map( 'trim', explode( "\n", $lines ) ); $candidatesByLocale = []; $candidatesByLang = []; - foreach ( $lines as $line ) { if ( $line === '' ) { continue; @@ -1198,7 +1211,7 @@ abstract class Installer { $scriptTypes = [ 'php' => [ "readExtension( $fullJsonFile ); + if ( $info === false ) { + continue; + } + $exts[$file] += $info; + } } closedir( $dh ); uksort( $exts, 'strnatcasecmp' ); @@ -1318,6 +1346,82 @@ abstract class Installer { return $exts; } + /** + * @param string $fullJsonFile + * @param array $extDeps + * @param array $skinDeps + * + * @return array|bool False if this extension can't be loaded + */ + private function readExtension( $fullJsonFile, $extDeps = [], $skinDeps = [] ) { + $load = [ + $fullJsonFile => 1 + ]; + if ( $extDeps ) { + $extDir = $this->getVar( 'IP' ) . '/extensions'; + foreach ( $extDeps as $dep ) { + $fname = "$extDir/$dep/extension.json"; + if ( !file_exists( $fname ) ) { + return false; + } + $load[$fname] = 1; + } + } + if ( $skinDeps ) { + $skinDir = $this->getVar( 'IP' ) . '/skins'; + foreach ( $skinDeps as $dep ) { + $fname = "$skinDir/$dep/skin.json"; + if ( !file_exists( $fname ) ) { + return false; + } + $load[$fname] = 1; + } + } + $registry = new ExtensionRegistry(); + try { + $info = $registry->readFromQueue( $load ); + } catch ( ExtensionDependencyError $e ) { + if ( $e->incompatibleCore || $e->incompatibleSkins + || $e->incompatibleExtensions + ) { + // If something is incompatible with a dependency, we have no real + // option besides skipping it + return false; + } elseif ( $e->missingExtensions || $e->missingSkins ) { + // There's an extension missing in the dependency tree, + // so add those to the dependency list and try again + return $this->readExtension( + $fullJsonFile, + array_merge( $extDeps, $e->missingExtensions ), + array_merge( $skinDeps, $e->missingSkins ) + ); + } + // Some other kind of dependency error? + return false; + } + $ret = []; + // The order of credits will be the order of $load, + // so the first extension is the one we want to load, + // everything else is a dependency + $i = 0; + foreach ( $info['credits'] as $name => $credit ) { + $i++; + if ( $i == 1 ) { + // Extension we want to load + continue; + } + $type = basename( $credit['path'] ) === 'skin.json' ? 'skins' : 'extensions'; + $ret['requires'][$type][] = $credit['name']; + } + $credits = array_values( $info['credits'] )[0]; + if ( isset( $credits['url'] ) ) { + $ret['url'] = $credits['url']; + } + $ret['type'] = $credits['type']; + + return $ret; + } + /** * Returns a default value to be used for $wgDefaultSkin: normally the one set in DefaultSettings, * but will fall back to another if the default skin is missing and some other one is present @@ -1345,6 +1449,10 @@ abstract class Installer { $exts = $this->getVar( '_Extensions' ); $IP = $this->getVar( 'IP' ); + // Marker for DatabaseUpdater::loadExtensions so we don't + // double load extensions + define( 'MW_EXTENSIONS_LOADED', true ); + /** * We need to include DefaultSettings before including extensions to avoid * warnings about unset variables. However, the only thing we really