47 '_InstallUser' =>
'postgres',
69 $this->parent->getHelpBox(
'config-db-host-help' )
71 $this->
getTextBox(
'wgDBport',
'config-db-port' ) .
72 Html::openElement(
'fieldset' ) .
73 Html::element(
'legend', [],
wfMessage(
'config-db-wiki-settings' )->text() ) .
78 $this->parent->getHelpBox(
'config-db-name-help' )
84 $this->parent->getHelpBox(
'config-db-schema-help' )
86 Html::closeElement(
'fieldset' ) .
100 $status = Status::newGood();
101 if ( !strlen( $newValues[
'wgDBname'] ) ) {
102 $status->fatal(
'config-missing-db-name' );
103 } elseif ( !preg_match(
'/^[a-zA-Z0-9_]+$/', $newValues[
'wgDBname'] ) ) {
104 $status->fatal(
'config-invalid-db-name', $newValues[
'wgDBname'] );
106 if ( !preg_match(
'/^[a-zA-Z0-9_]*$/', $newValues[
'wgDBmwschema'] ) ) {
107 $status->fatal(
'config-invalid-schema', $newValues[
'wgDBmwschema'] );
111 if ( $status->isOK() ) {
114 if ( !$status->isOK() ) {
119 if ( !$status->isOK() ) {
125 $conn = $status->value;
128 $version = $conn->getServerVersion();
129 $status = static::meetsMinimumRequirement( $version );
130 if ( !$status->isOK() ) {
134 $this->
setVar(
'wgDBuser', $this->
getVar(
'_InstallUser' ) );
135 $this->
setVar(
'wgDBpassword', $this->
getVar(
'_InstallPassword' ) );
137 return Status::newGood();
142 if ( $status->isOK() ) {
143 $this->db = $status->value;
162 $status = Status::newGood();
164 $db = Database::factory(
'postgres', [
165 'host' => $this->
getVar(
'wgDBserver' ),
166 'port' => $this->
getVar(
'wgDBport' ),
168 'password' => $password,
171 'keywordTableMap' => [
'user' =>
'mwuser',
'text' =>
'pagecontent' ],
173 $status->value =
$db;
175 $status->fatal(
'config-connection-error', $e->getMessage() );
187 if ( isset( $this->pgConns[
$type] ) ) {
188 return Status::newGood( $this->pgConns[
$type] );
192 if ( $status->isOK() ) {
196 $conn = $status->value;
198 $conn->commit( __METHOD__ );
199 $this->pgConns[
$type] = $conn;
234 $this->
getVar(
'_InstallUser' ),
235 $this->
getVar(
'_InstallPassword' ) );
236 case 'create-schema':
238 $this->
getVar(
'_InstallUser' ),
239 $this->
getVar(
'_InstallPassword' ),
240 $this->
getVar(
'wgDBname' ),
241 $this->
getVar(
'wgDBmwschema' ) );
242 case 'create-tables':
244 if ( $status->isOK() ) {
248 $conn = $status->value;
249 $safeRole = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
250 $conn->query(
"SET ROLE $safeRole", __METHOD__ );
255 throw new MWException(
"Invalid special connection type: \"$type\"" );
264 if ( !in_array( $this->
getVar(
'wgDBname' ), $dbs ) ) {
265 array_unshift( $dbs, $this->
getVar(
'wgDBname' ) );
268 $status = Status::newGood();
269 foreach ( $dbs as
$db ) {
272 'host' => $this->
getVar(
'wgDBserver' ),
273 'port' => $this->
getVar(
'wgDBport' ),
275 'password' => $password,
278 $conn = Database::factory(
'postgres', $p );
281 $status->fatal(
'config-pg-test-error',
$db,
282 $error->getMessage() );
284 if ( $conn !==
false ) {
288 if ( $conn !==
false ) {
289 return Status::newGood( $conn );
297 if ( !$status->isOK() ) {
303 $conn = $status->value;
304 $superuser = $this->
getVar(
'_InstallUser' );
306 $row = $conn->selectRow(
'"pg_catalog"."pg_roles"',
'*',
307 [
'rolname' => $superuser ], __METHOD__ );
318 return $perms->rolsuper ===
't' || $perms->rolcreaterole ===
't';
327 return $perms->rolsuper ===
't';
332 $noCreateMsg =
false;
334 $noCreateMsg =
'config-db-web-no-create-privs';
343 if ( !$status->isOK() ) {
347 $same = $this->
getVar(
'wgDBuser' ) === $this->
getVar(
'_InstallUser' );
355 if ( !$status->isOK() ) {
359 $exists = $status->value->roleExists( $this->
getVar(
'wgDBuser' ) );
364 $create = $this->
getVar(
'_CreateDBAccount' );
366 $this->
setVar(
'_CreateDBAccount',
false );
370 if ( !$create && !$exists ) {
372 $msg =
'config-install-user-missing-create';
374 $msg =
'config-install-user-missing';
377 return Status::newFatal( $msg, $this->
getVar(
'wgDBuser' ) );
382 return Status::newGood();
387 $this->
getVar(
'wgDBuser' ),
388 $this->
getVar(
'wgDBpassword' ) );
389 if ( !$status->isOK() ) {
397 return Status::newGood();
399 return Status::newFatal(
'config-pg-not-in-role' );
414 if ( !$status->isOK() ) {
417 $conn = $status->value;
418 $installerId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
419 [
'rolname' => $this->
getVar(
'_InstallUser' ) ], __METHOD__ );
420 $webId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
421 [
'rolname' => $this->
getVar(
'wgDBuser' ) ], __METHOD__ );
423 return $this->
isRoleMember( $conn, $installerId, $webId, $this->maxRoleSearchDepth );
434 protected function isRoleMember( $conn, $targetMember, $group, $maxDepth ) {
435 if ( $targetMember === $group ) {
440 $res = $conn->select(
'"pg_catalog"."pg_auth_members"', [
'member' ],
441 [
'roleid' => $group ], __METHOD__ );
442 foreach (
$res as $row ) {
443 if ( $row->member == $targetMember ) {
449 if ( $maxDepth > 0 &&
450 $this->
isRoleMember( $conn, $targetMember, $row->member, $maxDepth - 1 )
463 'callback' => [ $this,
'setupUser' ],
466 'name' =>
'pg-commit',
467 'callback' => [ $this,
'commitChanges' ],
470 'name' =>
'pg-plpgsql',
471 'callback' => [ $this,
'setupPLpgSQL' ],
475 'callback' => [ $this,
'setupSchema' ]
478 if ( $this->
getVar(
'_CreateDBAccount' ) ) {
479 $this->parent->addInstallStep( $createDbAccount,
'database' );
481 $this->parent->addInstallStep( $commitCB,
'interwiki' );
482 $this->parent->addInstallStep( $plpgCB,
'database' );
483 $this->parent->addInstallStep( $schemaCB,
'database' );
488 if ( !$status->isOK() ) {
491 $conn = $status->value;
493 $dbName = $this->
getVar(
'wgDBname' );
495 $exists = $conn->selectField(
'"pg_catalog"."pg_database"',
'1',
496 [
'datname' => $dbName ], __METHOD__ );
498 $safedb = $conn->addIdentifierQuotes( $dbName );
499 $conn->query(
"CREATE DATABASE $safedb", __METHOD__ );
502 return Status::newGood();
508 if ( !$status->isOK() ) {
512 $conn = $status->value;
513 '@phan-var DatabasePostgres $conn';
516 $schema = $this->
getVar(
'wgDBmwschema' );
517 $safeschema = $conn->addIdentifierQuotes( $schema );
518 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
519 if ( !$conn->schemaExists( $schema ) ) {
521 $conn->query(
"CREATE SCHEMA $safeschema AUTHORIZATION $safeuser", __METHOD__ );
523 return Status::newFatal(
'config-install-pg-schema-failed',
524 $this->
getVar(
'_InstallUser' ), $schema );
529 $conn->determineCoreSchema( $schema );
531 return Status::newGood();
535 $this->db->commit( __METHOD__ );
537 return Status::newGood();
541 if ( !$this->
getVar(
'_CreateDBAccount' ) ) {
542 return Status::newGood();
546 if ( !$status->isOK() ) {
550 $conn = $status->value;
551 '@phan-var DatabasePostgres $conn';
553 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
554 $safepass = $conn->addQuotes( $this->
getVar(
'wgDBpassword' ) );
557 $userExists = $conn->roleExists( $this->
getVar(
'wgDBuser' ) );
558 if ( !$userExists ) {
561 $sql =
"CREATE ROLE $safeuser NOCREATEDB LOGIN PASSWORD $safepass";
567 $sql .=
' ROLE' . $conn->addIdentifierQuotes( $this->
getVar(
'_InstallUser' ) );
570 $conn->query( $sql, __METHOD__ );
572 return Status::newFatal(
'config-install-user-create-failed',
573 $this->
getVar(
'wgDBuser' ), $e->getMessage() );
577 return Status::newGood();
581 $port = $this->
getVar(
'wgDBport' );
582 $schema = $this->
getVar(
'wgDBmwschema' );
584 return "# Postgres specific settings
585\$wgDBport = \"{$port}\";
586\$wgDBmwschema = \"{$schema}\";";
592 # Normal user and password are selected after this step, so for now
593 # just copy these two
595 $wgDBpassword = $this->
getVar(
'_InstallPassword' );
599 $schema = $this->
getVar(
'wgDBmwschema' );
602 if ( !$status->isOK() ) {
607 $conn = $status->value;
608 '@phan-var DatabasePostgres $conn';
610 if ( $conn->tableExists(
'archive', __METHOD__ ) ) {
611 $status->warning(
'config-install-tables-exist' );
617 $conn->begin( __METHOD__ );
619 if ( !$conn->schemaExists( $schema ) ) {
620 $status->fatal(
'config-install-pg-schema-not-exist' );
625 if ( $error !==
true ) {
626 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
627 $conn->rollback( __METHOD__ );
628 $status->fatal(
'config-install-tables-manual-failed', $error );
631 if ( $error !==
true ) {
632 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
633 $conn->rollback( __METHOD__ );
634 $status->fatal(
'config-install-tables-failed', $error );
636 $conn->commit( __METHOD__ );
640 if ( $status->isOK() ) {
650 return array_merge( parent::getGlobalDefaults(), [
651 'wgDBmwschema' =>
'mediawiki',
659 if ( !$status->isOK() ) {
665 $conn = $status->value;
667 $exists = $conn->selectField(
'"pg_catalog"."pg_language"',
'1',
668 [
'lanname' =>
'plpgsql' ], __METHOD__ );
671 return Status::newGood();
676 $exists = $conn->selectField(
677 [
'"pg_catalog"."pg_class"',
'"pg_catalog"."pg_namespace"' ],
680 'pg_namespace.oid=relnamespace',
681 'nspname' =>
'pg_catalog',
682 'relname' =>
'pg_pltemplate',
687 $conn->query(
'CREATE LANGUAGE plpgsql' );
689 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
692 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
695 return Status::newGood();
$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.
enableLB()
Set up LBFactory so that wfGetDB() etc.
Database $db
The database connection.
getGeneratedSchemaPath( $db)
Return a path to the DBMS-specific automatically generated schema file.
setVarsFromRequest( $varNames)
Convenience function to set variables based on form data.
getSchemaPath( $db)
Return a path to the DBMS-specific schema file, otherwise default to tables.sql Stable to override.
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.
Class for setting up the MediaWiki database using Postgres.
getConnection()
Connect to the database using the administrative user/password currently defined in the session.
getPgConnection( $type)
Get a special type of connection.
openConnectionToAnyDB( $user, $password)
getName()
Return the internal name, e.g.
openConnectionWithParams( $user, $password, $dbName, $schema)
Open a PG connection with given parameters.
preUpgrade()
Allow DB installers a chance to make checks before upgrade.
setupDatabase()
Create the database and return a Status object indicating success or failure.
getGlobalDefaults()
Get a name=>value map of MW configuration globals for the default values.
createTables()
Create database tables from scratch from the automatically generated file Stable to override.
getConnectForm()
Get HTML for a web form that configures this database.
submitSettingsForm()
Set variables based on the request array, assuming it was submitted via the form return by getSetting...
static $notMinimumVersionMessage
preInstall()
Allow DB installers a chance to make last-minute changes before installation occurs.
openConnection()
Open a connection to the database using the administrative user/password currently defined in the ses...
getInstallUserPermissions()
isRoleMember( $conn, $targetMember, $group, $maxDepth)
Recursive helper for canCreateObjectsForWebUser().
canCreateObjectsForWebUser()
Returns true if the install user is able to create objects owned by the web user, false otherwise.
getSettingsForm()
Get HTML for a web form that retrieves settings used for installation.
getLocalSettings()
Get the DBMS-specific options for LocalSettings.php generation.
openPgConnection( $type)
Get a connection of a specific PostgreSQL-specific type.
submitConnectForm()
Set variables based on the request array, assuming it was submitted via the form returned by getConne...