Allow the extensions and skins installed by maintenance/install.php to be customised using --skins= and --extensions=. If the argument is am empty string then no extensions/skins are installed. For backwards compatibility, the default is to install all skins, but to install all extensions only if --with-extensions is given. The new CLI options may be specified multiple times, but for convenience, comma-separated lists can also be used. Also: * Rename $option to $options * If an extension has a dependency error, propagate the very readable error message generated by ExtensionRegistry back to the user. * Split getExtensionInfo() from the loop body of findExtensionsByType(), so that CliInstaller can use it to validate its parameters and get error messages. * I didn't like the idea of removing the "s" from the directory name in order to construct the JSON file name, so I split findExtensionsByType() from findExtensions(), with the former not having this hack. In findExtensions(), make the previous assumption that the directory name is always "extensions" or "skins" explicit, throwing an exception if it is otherwise. Change-Id: Id0fb63cd4e61a047ef3396ee1c38d6073dfc7fd1
266 lines
7 KiB
PHP
266 lines
7 KiB
PHP
<?php
|
|
/**
|
|
* Core installer command line interface.
|
|
*
|
|
* 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 Deployment
|
|
*/
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
/**
|
|
* Class for the core installer command line interface.
|
|
*
|
|
* @ingroup Deployment
|
|
* @since 1.17
|
|
*/
|
|
class CliInstaller extends Installer {
|
|
private $specifiedScriptPath = false;
|
|
|
|
private $optionMap = [
|
|
'dbtype' => 'wgDBtype',
|
|
'dbserver' => 'wgDBserver',
|
|
'dbname' => 'wgDBname',
|
|
'dbuser' => 'wgDBuser',
|
|
'dbpass' => 'wgDBpassword',
|
|
'dbprefix' => 'wgDBprefix',
|
|
'dbtableoptions' => 'wgDBTableOptions',
|
|
'dbport' => 'wgDBport',
|
|
'dbschema' => 'wgDBmwschema',
|
|
'dbpath' => 'wgSQLiteDataDir',
|
|
'server' => 'wgServer',
|
|
'scriptpath' => 'wgScriptPath',
|
|
];
|
|
|
|
/**
|
|
* @param string $siteName
|
|
* @param string|null $admin
|
|
* @param array $options
|
|
*/
|
|
function __construct( $siteName, $admin = null, array $options = [] ) {
|
|
global $wgContLang;
|
|
|
|
parent::__construct();
|
|
|
|
if ( isset( $options['scriptpath'] ) ) {
|
|
$this->specifiedScriptPath = true;
|
|
}
|
|
|
|
foreach ( $this->optionMap as $opt => $global ) {
|
|
if ( isset( $options[$opt] ) ) {
|
|
$GLOBALS[$global] = $options[$opt];
|
|
$this->setVar( $global, $options[$opt] );
|
|
}
|
|
}
|
|
|
|
if ( isset( $options['lang'] ) ) {
|
|
global $wgLang, $wgLanguageCode;
|
|
$this->setVar( '_UserLang', $options['lang'] );
|
|
$wgLanguageCode = $options['lang'];
|
|
$wgContLang = MediaWikiServices::getInstance()->getContentLanguage();
|
|
$wgLang = Language::factory( $options['lang'] );
|
|
RequestContext::getMain()->setLanguage( $wgLang );
|
|
}
|
|
|
|
$this->setVar( 'wgSitename', $siteName );
|
|
|
|
$metaNS = $wgContLang->ucfirst( str_replace( ' ', '_', $siteName ) );
|
|
if ( $metaNS == 'MediaWiki' ) {
|
|
$metaNS = 'Project';
|
|
}
|
|
$this->setVar( 'wgMetaNamespace', $metaNS );
|
|
|
|
if ( $admin ) {
|
|
$this->setVar( '_AdminName', $admin );
|
|
}
|
|
|
|
if ( !isset( $options['installdbuser'] ) ) {
|
|
$this->setVar( '_InstallUser',
|
|
$this->getVar( 'wgDBuser' ) );
|
|
$this->setVar( '_InstallPassword',
|
|
$this->getVar( 'wgDBpassword' ) );
|
|
} else {
|
|
$this->setVar( '_InstallUser',
|
|
$options['installdbuser'] );
|
|
$this->setVar( '_InstallPassword',
|
|
$options['installdbpass'] ?? "" );
|
|
|
|
// Assume that if we're given the installer user, we'll create the account.
|
|
$this->setVar( '_CreateDBAccount', true );
|
|
}
|
|
|
|
if ( isset( $options['pass'] ) ) {
|
|
$this->setVar( '_AdminPassword', $options['pass'] );
|
|
}
|
|
|
|
// Detect and inject any extension found
|
|
if ( isset( $options['extensions'] ) ) {
|
|
$status = $this->validateExtensions(
|
|
'extension', 'extensions', $options['extensions'] );
|
|
if ( !$status->isOK() ) {
|
|
$this->showStatusMessage( $status );
|
|
}
|
|
$this->setVar( '_Extensions', $status->value );
|
|
} elseif ( isset( $options['with-extensions'] ) ) {
|
|
$this->setVar( '_Extensions', array_keys( $this->findExtensions() ) );
|
|
}
|
|
|
|
// Set up the default skins
|
|
if ( isset( $options['skins'] ) ) {
|
|
$status = $this->validateExtensions( 'skin', 'skins', $options['skins'] );
|
|
if ( !$status->isOK() ) {
|
|
$this->showStatusMessage( $status );
|
|
}
|
|
$skins = $status->value;
|
|
} else {
|
|
$skins = array_keys( $this->findExtensions( 'skins' ) );
|
|
}
|
|
$this->setVar( '_Skins', $skins );
|
|
|
|
if ( $skins ) {
|
|
$skinNames = array_map( 'strtolower', $skins );
|
|
$this->setVar( 'wgDefaultSkin', $this->getDefaultSkin( $skinNames ) );
|
|
}
|
|
}
|
|
|
|
private function validateExtensions( $type, $directory, $nameLists ) {
|
|
$extensions = [];
|
|
$status = new Status;
|
|
foreach ( (array)$nameLists as $nameList ) {
|
|
foreach ( explode( ',', $nameList ) as $name ) {
|
|
$name = trim( $name );
|
|
if ( $name === '' ) {
|
|
continue;
|
|
}
|
|
$extStatus = $this->getExtensionInfo( $type, $directory, $name );
|
|
if ( $extStatus->isOK() ) {
|
|
$extensions[] = $name;
|
|
} else {
|
|
$status->merge( $extStatus );
|
|
}
|
|
}
|
|
}
|
|
$extensions = array_unique( $extensions );
|
|
$status->value = $extensions;
|
|
return $status;
|
|
}
|
|
|
|
/**
|
|
* Main entry point.
|
|
*/
|
|
public function execute() {
|
|
$vars = Installer::getExistingLocalSettings();
|
|
if ( $vars ) {
|
|
$this->showStatusMessage(
|
|
Status::newFatal( "config-localsettings-cli-upgrade" )
|
|
);
|
|
}
|
|
|
|
$this->performInstallation(
|
|
[ $this, 'startStage' ],
|
|
[ $this, 'endStage' ]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Write LocalSettings.php to a given path
|
|
*
|
|
* @param string $path Full path to write LocalSettings.php to
|
|
*/
|
|
public function writeConfigurationFile( $path ) {
|
|
$ls = InstallerOverrides::getLocalSettingsGenerator( $this );
|
|
$ls->writeFile( "$path/LocalSettings.php" );
|
|
}
|
|
|
|
public function startStage( $step ) {
|
|
// Messages: config-install-database, config-install-tables, config-install-interwiki,
|
|
// config-install-stats, config-install-keys, config-install-sysop, config-install-mainpage,
|
|
// config-install-extensions
|
|
$this->showMessage( "config-install-$step" );
|
|
}
|
|
|
|
public function endStage( $step, $status ) {
|
|
$this->showStatusMessage( $status );
|
|
$this->showMessage( 'config-install-step-done' );
|
|
}
|
|
|
|
public function showMessage( $msg /*, ... */ ) {
|
|
echo $this->getMessageText( func_get_args() ) . "\n";
|
|
flush();
|
|
}
|
|
|
|
public function showError( $msg /*, ... */ ) {
|
|
echo "***{$this->getMessageText( func_get_args() )}***\n";
|
|
flush();
|
|
}
|
|
|
|
/**
|
|
* @param array $params
|
|
*
|
|
* @return string
|
|
*/
|
|
protected function getMessageText( $params ) {
|
|
$msg = array_shift( $params );
|
|
|
|
$text = wfMessage( $msg, $params )->parse();
|
|
|
|
$text = preg_replace( '/<a href="(.*?)".*?>(.*?)<\/a>/', '$2 <$1>', $text );
|
|
|
|
return Sanitizer::stripAllTags( $text );
|
|
}
|
|
|
|
/**
|
|
* Dummy
|
|
*/
|
|
public function showHelpBox( $msg /*, ... */ ) {
|
|
}
|
|
|
|
public function showStatusMessage( Status $status ) {
|
|
$warnings = array_merge( $status->getWarningsArray(),
|
|
$status->getErrorsArray() );
|
|
|
|
if ( count( $warnings ) !== 0 ) {
|
|
foreach ( $warnings as $w ) {
|
|
$this->showMessage( ...$w );
|
|
}
|
|
}
|
|
|
|
if ( !$status->isOK() ) {
|
|
echo "\n";
|
|
exit( 1 );
|
|
}
|
|
}
|
|
|
|
public function envCheckPath() {
|
|
if ( !$this->specifiedScriptPath ) {
|
|
$this->showMessage( 'config-no-cli-uri', $this->getVar( "wgScriptPath" ) );
|
|
}
|
|
|
|
return parent::envCheckPath();
|
|
}
|
|
|
|
protected function envGetDefaultServer() {
|
|
return null; // Do not guess if installing from CLI
|
|
}
|
|
|
|
public function dirIsExecutable( $dir, $url ) {
|
|
$this->showMessage( 'config-no-cli-uploads-check', $dir );
|
|
|
|
return false;
|
|
}
|
|
}
|