46 '_MysqlEngine' =>
'InnoDB',
47 '_MysqlCharset' =>
'binary',
48 '_InstallUser' =>
'root',
61 'CREATE TEMPORARY TABLES',
86 $this->parent->getHelpBox(
'config-db-host-help' )
88 Html::openElement(
'fieldset' ) .
89 Html::element(
'legend', [],
wfMessage(
'config-db-wiki-settings' )->text() ) .
90 $this->
getTextBox(
'wgDBname',
'config-db-name', [
'dir' =>
'ltr' ],
91 $this->parent->getHelpBox(
'config-db-name-help' ) ) .
92 $this->
getTextBox(
'wgDBprefix',
'config-db-prefix', [
'dir' =>
'ltr' ],
93 $this->parent->getHelpBox(
'config-db-prefix-help' ) ) .
94 Html::closeElement(
'fieldset' ) .
103 $status = Status::newGood();
104 if ( !strlen( $newValues[
'wgDBserver'] ) ) {
105 $status->fatal(
'config-missing-db-host' );
107 if ( !strlen( $newValues[
'wgDBname'] ) ) {
108 $status->fatal(
'config-missing-db-name' );
109 } elseif ( !preg_match(
'/^[a-z0-9+_-]+$/i', $newValues[
'wgDBname'] ) ) {
110 $status->fatal(
'config-invalid-db-name', $newValues[
'wgDBname'] );
112 if ( !preg_match(
'/^[a-z0-9_-]*$/i', $newValues[
'wgDBprefix'] ) ) {
113 $status->fatal(
'config-invalid-db-prefix', $newValues[
'wgDBprefix'] );
115 if ( !$status->isOK() ) {
121 if ( !$status->isOK() ) {
127 if ( !$status->isOK() ) {
133 $conn = $status->value;
134 '@phan-var Database $conn';
137 return static::meetsMinimumRequirement( $conn->getServerVersion() );
144 $status = Status::newGood();
147 $db = Database::factory(
'mysql', [
148 'host' => $this->
getVar(
'wgDBserver' ),
149 'user' => $this->
getVar(
'_InstallUser' ),
150 'password' => $this->
getVar(
'_InstallPassword' ),
153 'tablePrefix' => $this->
getVar(
'wgDBprefix' ) ] );
154 $status->value =
$db;
156 $status->fatal(
'config-connection-error', $e->getMessage() );
166 if ( !$status->isOK() ) {
167 $this->parent->showStatusMessage( $status );
174 $conn = $status->value;
175 $conn->selectDB( $this->
getVar(
'wgDBname' ) );
177 # Determine existing default character set
178 if ( $conn->tableExists(
"revision", __METHOD__ ) ) {
180 $res = $conn->query(
"SHOW TABLE STATUS LIKE '$revision'", __METHOD__ );
181 $row = $conn->fetchObject(
$res );
183 $this->parent->showMessage(
'config-show-table-status' );
184 $existingSchema =
false;
185 $existingEngine =
false;
187 if ( preg_match(
'/^latin1/', $row->Collation ) ) {
188 $existingSchema =
'latin1';
189 } elseif ( preg_match(
'/^utf8/', $row->Collation ) ) {
190 $existingSchema =
'utf8';
191 } elseif ( preg_match(
'/^binary/', $row->Collation ) ) {
192 $existingSchema =
'binary';
194 $existingSchema =
false;
195 $this->parent->showMessage(
'config-unknown-collation' );
197 $existingEngine = $row->Engine ?? $row->Type;
200 $existingSchema =
false;
201 $existingEngine =
false;
204 if ( $existingSchema && $existingSchema != $this->
getVar(
'_MysqlCharset' ) ) {
205 $this->
setVar(
'_MysqlCharset', $existingSchema );
207 if ( $existingEngine && $existingEngine != $this->
getVar(
'_MysqlEngine' ) ) {
208 $this->
setVar(
'_MysqlEngine', $existingEngine );
211 # Normal user and password are selected after this step, so for now
212 # just copy these two
214 $wgDBpassword = $this->
getVar(
'_InstallPassword' );
223 return str_replace( [ $escapeChar,
'%',
'_' ],
224 [
"{$escapeChar}{$escapeChar}",
"{$escapeChar}%",
"{$escapeChar}_" ],
239 $conn = $status->value;
242 $res = $conn->query(
'SHOW ENGINES', __METHOD__ );
243 foreach (
$res as $row ) {
244 if ( $row->Support ==
'YES' || $row->Support ==
'DEFAULT' ) {
245 $engines[] = $row->Engine;
248 $engines = array_intersect( $this->supportedEngines, $engines );
259 return [
'binary',
'utf8' ];
269 if ( !$status->isOK() ) {
273 $conn = $status->value;
276 $currentName = $conn->selectField(
'',
'CURRENT_USER()',
'', __METHOD__ );
277 $parts = explode(
'@', $currentName );
278 if ( count( $parts ) != 2 ) {
281 $quotedUser = $conn->addQuotes( $parts[0] ) .
282 '@' . $conn->addQuotes( $parts[1] );
286 $res = $conn->select(
'INFORMATION_SCHEMA.USER_PRIVILEGES',
'*',
287 [
'GRANTEE' => $quotedUser ], __METHOD__ );
288 $insertMysql =
false;
289 $grantOptions = array_fill_keys( $this->webUserPrivs,
true );
290 foreach (
$res as $row ) {
291 if ( $row->PRIVILEGE_TYPE ==
'INSERT' ) {
294 if ( $row->IS_GRANTABLE ) {
295 unset( $grantOptions[$row->PRIVILEGE_TYPE] );
300 if ( !$insertMysql ) {
301 $row = $conn->selectRow(
'INFORMATION_SCHEMA.SCHEMA_PRIVILEGES',
'*',
303 'GRANTEE' => $quotedUser,
304 'TABLE_SCHEMA' =>
'mysql',
305 'PRIVILEGE_TYPE' =>
'INSERT',
312 if ( !$insertMysql ) {
317 $res = $conn->select(
'INFORMATION_SCHEMA.SCHEMA_PRIVILEGES',
'*',
319 'GRANTEE' => $quotedUser,
322 foreach (
$res as $row ) {
324 if ( preg_match( $regex, $this->
getVar(
'wgDBname' ) ) ) {
325 unset( $grantOptions[$row->PRIVILEGE_TYPE] );
328 if ( count( $grantOptions ) ) {
343 $r = preg_quote( $wildcard,
'/' );
356 $noCreateMsg =
false;
358 $noCreateMsg =
'config-db-web-no-create-privs';
365 if ( !in_array( $this->
getVar(
'_MysqlEngine' ), $engines ) ) {
366 $this->
setVar(
'_MysqlEngine', reset( $engines ) );
371 if ( !in_array( $this->
getVar(
'_MysqlCharset' ), $charsets ) ) {
372 $this->
setVar(
'_MysqlCharset', reset( $charsets ) );
384 if ( !$status->isOK() ) {
391 $this->
setVar(
'_CreateDBAccount',
false );
394 $create = $this->
getVar(
'_CreateDBAccount' );
400 Database::factory(
'mysql', [
401 'host' => $this->
getVar(
'wgDBserver' ),
402 'user' => $this->
getVar(
'wgDBuser' ),
403 'password' => $this->
getVar(
'wgDBpassword' ),
406 'tablePrefix' => $this->
getVar(
'wgDBprefix' )
409 return Status::newFatal(
'config-connection-error', $e->getMessage() );
416 if ( !in_array( $this->
getVar(
'_MysqlEngine' ), $engines ) ) {
417 $this->
setVar(
'_MysqlEngine', reset( $engines ) );
420 if ( !in_array( $this->
getVar(
'_MysqlCharset' ), $charsets ) ) {
421 $this->
setVar(
'_MysqlCharset', reset( $charsets ) );
424 return Status::newGood();
428 # Add our user callback to installSteps, right before the tables are created.
431 'callback' => [ $this,
'setupUser' ],
433 $this->parent->addInstallStep( $callback,
'tables' );
441 if ( !$status->isOK() ) {
445 $conn = $status->value;
446 $dbName = $this->
getVar(
'wgDBname' );
449 "CREATE DATABASE " . $conn->addIdentifierQuotes( $dbName ) .
"CHARACTER SET utf8",
453 $conn->selectDB( $dbName );
465 $encDatabase = $this->db->addQuotes( $dbName );
467 return $this->db->query(
468 "SELECT 1 FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = $encDatabase",
477 $dbUser = $this->
getVar(
'wgDBuser' );
478 if ( $dbUser == $this->
getVar(
'_InstallUser' ) ) {
479 return Status::newGood();
482 if ( !$status->isOK() ) {
487 $dbName = $this->
getVar(
'wgDBname' );
488 $this->db->selectDB( $dbName );
489 $server = $this->
getVar(
'wgDBserver' );
490 $password = $this->
getVar(
'wgDBpassword' );
491 $grantableNames = [];
493 if ( $this->
getVar(
'_CreateDBAccount' ) ) {
496 Database::factory(
'mysql', [
499 'password' => $password,
502 'tablePrefix' => $this->
getVar(
'wgDBprefix' )
505 $tryToCreate =
false;
511 $tryToCreate =
false;
514 if ( $tryToCreate ) {
518 'localhost.localdomain',
522 $createHostList = array_unique( $createHostList );
523 $escPass = $this->db->addQuotes( $password );
525 foreach ( $createHostList as $host ) {
529 $this->db->begin( __METHOD__ );
530 $this->db->query(
"CREATE USER $fullName IDENTIFIED BY $escPass", __METHOD__ );
531 $this->db->commit( __METHOD__ );
532 $grantableNames[] = $fullName;
534 if ( $this->db->lastErrno() == 1396 ) {
536 $this->db->rollback( __METHOD__ );
537 $status->warning(
'config-install-user-alreadyexists', $dbUser );
538 $grantableNames[] = $fullName;
543 $this->db->rollback( __METHOD__ );
544 $status->warning(
'config-install-user-create-failed', $dbUser, $dqe->getMessage() );
548 $status->warning(
'config-install-user-alreadyexists', $dbUser );
549 $grantableNames[] = $fullName;
556 $dbAllTables = $this->db->addIdentifierQuotes( $dbName ) .
'.*';
557 foreach ( $grantableNames as $name ) {
559 $this->db->begin( __METHOD__ );
560 $this->db->query(
"GRANT ALL PRIVILEGES ON $dbAllTables TO $name", __METHOD__ );
561 $this->db->commit( __METHOD__ );
563 $this->db->rollback( __METHOD__ );
564 $status->fatal(
'config-install-user-grant-failed', $dbUser, $dqe->getMessage() );
578 return $this->db->addQuotes( $name ) .
'@' . $this->db->addQuotes( $host );
590 $res = $this->db->selectRow(
'mysql.user', [
'Host',
'User' ],
591 [
'Host' => $host,
'User' => $user ], __METHOD__ );
607 if ( $this->
getVar(
'_MysqlEngine' ) !==
null ) {
608 $options[] =
"ENGINE=" . $this->
getVar(
'_MysqlEngine' );
610 if ( $this->
getVar(
'_MysqlCharset' ) !==
null ) {
611 $options[] =
'DEFAULT CHARSET=' . $this->
getVar(
'_MysqlCharset' );
614 return implode(
', ', $options );
625 'wgDBname' => $this->
getVar(
'wgDBname' ),
626 'wgDBuser' => $this->
getVar(
'wgDBuser' ),
627 'wgDBpassword' => $this->
getVar(
'wgDBpassword' ),
632 $prefix = LocalSettingsGenerator::escapePhpString( $this->
getVar(
'wgDBprefix' ) );
633 $tblOpts = LocalSettingsGenerator::escapePhpString( $this->
getTableOptions() );
635 return "# MySQL specific settings
636\$wgDBprefix = \"{$prefix}\";
638# MySQL table options to use during installation or update
639\$wgDBTableOptions = \"{$tblOpts}\";";
$wgDBuser
Database username.
$wgDBpassword
Database user's password.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Base class for DBMS-specific installation helper classes.
getWebUserBox( $noCreateMsg=false)
Get a standard web-user fieldset.
submitWebUserBox()
Submit the form from getWebUserBox().
static checkExtension( $name)
Convenience function.
Database $db
The database connection.
setVarsFromRequest( $varNames)
Convenience function to set variables based on form data.
getConnection()
Connect to the database using the administrative user/password currently defined in the session.
getVar( $var, $default=null)
Get a variable, taking local defaults into account.
getTextBox( $var, $label, $attribs=[], $helpData="")
Get a labelled text box to configure a local variable.
setVar( $name, $value)
Convenience alias for $this->parent->setVar()
submitInstallUserBox()
Submit a standard install user fieldset.
getInstallUserBox()
Get a standard install-user fieldset.
setupSchemaVars()
Set appropriate schema variables in the current database connection.
Class for setting up the MediaWiki database using MySQL.
likeToRegex( $wildcard)
Convert a wildcard (as used in LIKE) to a regex Slashes are escaped, slash terminators included.
userDefinitelyExists( $host, $user)
Try to see if the user account exists.
escapeLikeInternal( $s, $escapeChar='`')
getSchemaVars()
Get variables to substitute into tables.sql and the SQL patch files.
preInstall()
Allow DB installers a chance to make last-minute changes before installation occurs.
databaseExists( $dbName)
Try to see if a given database exists.
getEngines()
Get a list of storage engines that are available and supported.
canCreateAccounts()
Return true if the install user can create accounts.
preUpgrade()
Allow DB installers a chance to make checks before upgrade.
getTableOptions()
Return any table options to be applied to all tables that don't override them.
getCharsets()
Get a list of character sets that are available and supported.
static $notMinimumVersionMessage
submitConnectForm()
Set variables based on the request array, assuming it was submitted via the form returned by getConne...
buildFullUserName( $name, $host)
Return a formal 'User'@'Host' username for use in queries.
getLocalSettings()
Get the DBMS-specific options for LocalSettings.php generation.
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s