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,
172 $status->value =
$db;
174 $status->fatal(
'config-connection-error', $e->getMessage() );
186 if ( isset( $this->pgConns[
$type] ) ) {
187 return Status::newGood( $this->pgConns[
$type] );
191 if ( $status->isOK() ) {
195 $conn = $status->value;
197 $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 = (bool)$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' );
626 if ( $error !==
true ) {
627 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
628 $conn->rollback( __METHOD__ );
629 $status->fatal(
'config-install-tables-failed', $error );
632 if ( $error !==
true ) {
633 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
634 $conn->rollback( __METHOD__ );
635 $status->fatal(
'config-install-tables-manual-failed', $error );
637 $conn->commit( __METHOD__ );
641 if ( $status->isOK() ) {
650 return Status::newGood();
656 return array_merge( parent::getGlobalDefaults(), [
657 'wgDBmwschema' =>
'mediawiki',
665 if ( !$status->isOK() ) {
671 $conn = $status->value;
673 $exists = (bool)$conn->selectField(
'"pg_catalog"."pg_language"',
'1',
674 [
'lanname' =>
'plpgsql' ], __METHOD__ );
677 return Status::newGood();
682 $exists = (bool)$conn->selectField(
683 [
'"pg_catalog"."pg_class"',
'"pg_catalog"."pg_namespace"' ],
686 'pg_namespace.oid=relnamespace',
687 'nspname' =>
'pg_catalog',
688 'relname' =>
'pg_pltemplate',
693 $conn->query(
'CREATE LANGUAGE plpgsql', __METHOD__ );
695 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
698 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
701 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.
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.
createManualTables()
Create database tables from scratch.
createTables()
Create database tables from scratch from the automatically generated file.
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...
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s