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' ) .
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'] );
134 '@phan-var Database $conn';
137 return static::meetsMinimumRequirement( $conn->getServerVersion() );
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' ) ] );
156 $status->fatal(
'config-connection-error', $e->getMessage() );
167 $this->parent->showStatusMessage(
$status );
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}_" ],
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' ];
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_flip( $this->webUserPrivs );
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 ) );
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' )
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 ) );
428 # Add our user callback to installSteps, right before the tables are created.
431 'callback' => [ $this,
'setupUser' ],
433 $this->parent->addInstallStep( $callback,
'tables' );
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' ) ) {
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' ),
635 return "# MySQL specific settings
636 \$wgDBprefix = \"{$prefix}\";
638 # MySQL table options to use during installation or update
639 \$wgDBTableOptions = \"{$tblOpts}\";";