48 '_InstallUser' =>
'postgres',
70 $this->parent->getHelpBox(
'config-db-host-help' )
72 $this->
getTextBox(
'wgDBport',
'config-db-port' ) .
73 Html::openElement(
'fieldset' ) .
74 Html::element(
'legend', [],
wfMessage(
'config-db-wiki-settings' )->text() ) .
79 $this->parent->getHelpBox(
'config-db-name-help' )
85 $this->parent->getHelpBox(
'config-db-schema-help' )
87 Html::closeElement(
'fieldset' ) .
101 $status = Status::newGood();
102 if ( !strlen( $newValues[
'wgDBname'] ) ) {
103 $status->fatal(
'config-missing-db-name' );
104 } elseif ( !preg_match(
'/^[a-zA-Z0-9_]+$/', $newValues[
'wgDBname'] ) ) {
105 $status->fatal(
'config-invalid-db-name', $newValues[
'wgDBname'] );
107 if ( !preg_match(
'/^[a-zA-Z0-9_]*$/', $newValues[
'wgDBmwschema'] ) ) {
108 $status->fatal(
'config-invalid-schema', $newValues[
'wgDBmwschema'] );
112 if ( $status->isOK() ) {
115 if ( !$status->isOK() ) {
120 if ( !$status->isOK() ) {
126 $conn = $status->value;
129 $status = static::meetsMinimumRequirement( $conn );
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 = MediaWikiServices::getInstance()->getDatabaseFactory()->create(
'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__ );
198 $this->pgConns[
$type] = $conn;
233 $this->
getVar(
'_InstallUser' ),
234 $this->
getVar(
'_InstallPassword' ) );
235 case 'create-schema':
237 $this->
getVar(
'_InstallUser' ),
238 $this->
getVar(
'_InstallPassword' ),
239 $this->
getVar(
'wgDBname' ),
240 $this->
getVar(
'wgDBmwschema' ) );
241 case 'create-tables':
243 if ( $status->isOK() ) {
247 $conn = $status->value;
248 $safeRole = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
249 $conn->query(
"SET ROLE $safeRole", __METHOD__ );
254 throw new MWException(
"Invalid special connection type: \"$type\"" );
263 if ( !in_array( $this->
getVar(
'wgDBname' ), $dbs ) ) {
264 array_unshift( $dbs, $this->
getVar(
'wgDBname' ) );
267 $status = Status::newGood();
268 foreach ( $dbs as
$db ) {
271 'host' => $this->
getVar(
'wgDBserver' ),
272 'port' => $this->
getVar(
'wgDBport' ),
274 'password' => $password,
277 $conn = Database::factory(
'postgres', $p );
280 $status->fatal(
'config-pg-test-error',
$db,
281 $error->getMessage() );
283 if ( $conn !==
false ) {
287 if ( $conn !==
false ) {
288 return Status::newGood( $conn );
296 if ( !$status->isOK() ) {
302 $conn = $status->value;
303 $superuser = $this->
getVar(
'_InstallUser' );
305 $row = $conn->selectRow(
'"pg_catalog"."pg_roles"',
'*',
306 [
'rolname' => $superuser ], __METHOD__ );
317 return $perms->rolsuper ===
't' || $perms->rolcreaterole ===
't';
326 return $perms->rolsuper ===
't';
331 $noCreateMsg =
false;
333 $noCreateMsg =
'config-db-web-no-create-privs';
342 if ( !$status->isOK() ) {
346 $same = $this->
getVar(
'wgDBuser' ) === $this->
getVar(
'_InstallUser' );
354 if ( !$status->isOK() ) {
358 $exists = $status->value->roleExists( $this->
getVar(
'wgDBuser' ) );
363 $create = $this->
getVar(
'_CreateDBAccount' );
365 $this->
setVar(
'_CreateDBAccount',
false );
369 if ( !$create && !$exists ) {
371 $msg =
'config-install-user-missing-create';
373 $msg =
'config-install-user-missing';
376 return Status::newFatal( $msg, $this->
getVar(
'wgDBuser' ) );
381 return Status::newGood();
386 $this->
getVar(
'wgDBuser' ),
387 $this->
getVar(
'wgDBpassword' ) );
388 if ( !$status->isOK() ) {
396 return Status::newGood();
398 return Status::newFatal(
'config-pg-not-in-role' );
413 if ( !$status->isOK() ) {
416 $conn = $status->value;
417 $installerId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
418 [
'rolname' => $this->
getVar(
'_InstallUser' ) ], __METHOD__ );
419 $webId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
420 [
'rolname' => $this->
getVar(
'wgDBuser' ) ], __METHOD__ );
422 return $this->
isRoleMember( $conn, $installerId, $webId, $this->maxRoleSearchDepth );
433 protected function isRoleMember( $conn, $targetMember, $group, $maxDepth ) {
434 if ( $targetMember === $group ) {
439 $res = $conn->select(
'"pg_catalog"."pg_auth_members"', [
'member' ],
440 [
'roleid' => $group ], __METHOD__ );
441 foreach (
$res as $row ) {
442 if ( $row->member == $targetMember ) {
448 if ( $maxDepth > 0 &&
449 $this->
isRoleMember( $conn, $targetMember, $row->member, $maxDepth - 1 )
462 'callback' => [ $this,
'setupUser' ],
465 'name' =>
'pg-commit',
466 'callback' => [ $this,
'commitChanges' ],
469 'name' =>
'pg-plpgsql',
470 'callback' => [ $this,
'setupPLpgSQL' ],
474 'callback' => [ $this,
'setupSchema' ]
477 if ( $this->
getVar(
'_CreateDBAccount' ) ) {
478 $this->parent->addInstallStep( $createDbAccount,
'database' );
480 $this->parent->addInstallStep( $commitCB,
'interwiki' );
481 $this->parent->addInstallStep( $plpgCB,
'database' );
482 $this->parent->addInstallStep( $schemaCB,
'database' );
487 if ( !$status->isOK() ) {
490 $conn = $status->value;
492 $dbName = $this->
getVar(
'wgDBname' );
494 $exists = (bool)$conn->selectField(
'"pg_catalog"."pg_database"',
'1',
495 [
'datname' => $dbName ], __METHOD__ );
497 $safedb = $conn->addIdentifierQuotes( $dbName );
498 $conn->query(
"CREATE DATABASE $safedb", __METHOD__ );
501 return Status::newGood();
507 if ( !$status->isOK() ) {
511 $conn = $status->value;
512 '@phan-var DatabasePostgres $conn';
515 $schema = $this->
getVar(
'wgDBmwschema' );
516 $safeschema = $conn->addIdentifierQuotes( $schema );
517 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
518 if ( !$conn->schemaExists( $schema ) ) {
520 $conn->query(
"CREATE SCHEMA $safeschema AUTHORIZATION $safeuser", __METHOD__ );
522 return Status::newFatal(
'config-install-pg-schema-failed',
523 $this->
getVar(
'_InstallUser' ), $schema );
528 $conn->determineCoreSchema( $schema );
530 return Status::newGood();
534 $this->db->commit( __METHOD__ );
536 return Status::newGood();
540 if ( !$this->
getVar(
'_CreateDBAccount' ) ) {
541 return Status::newGood();
545 if ( !$status->isOK() ) {
549 $conn = $status->value;
550 '@phan-var DatabasePostgres $conn';
552 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
553 $safepass = $conn->addQuotes( $this->
getVar(
'wgDBpassword' ) );
556 $userExists = $conn->roleExists( $this->
getVar(
'wgDBuser' ) );
557 if ( !$userExists ) {
560 $sql =
"CREATE ROLE $safeuser NOCREATEDB LOGIN PASSWORD $safepass";
566 $sql .=
' ROLE' . $conn->addIdentifierQuotes( $this->
getVar(
'_InstallUser' ) );
569 $conn->query( $sql, __METHOD__ );
571 return Status::newFatal(
'config-install-user-create-failed',
572 $this->
getVar(
'wgDBuser' ), $e->getMessage() );
576 return Status::newGood();
580 $port = $this->
getVar(
'wgDBport' );
581 $schema = $this->
getVar(
'wgDBmwschema' );
583 return "# Postgres specific settings
584\$wgDBport = \"{$port}\";
585\$wgDBmwschema = \"{$schema}\";";
591 # Normal user and password are selected after this step, so for now
592 # just copy these two
594 $wgDBpassword = $this->
getVar(
'_InstallPassword' );
598 $schema = $this->
getVar(
'wgDBmwschema' );
601 if ( !$status->isOK() ) {
606 $conn = $status->value;
607 '@phan-var DatabasePostgres $conn';
609 if ( $conn->tableExists(
'archive', __METHOD__ ) ) {
610 $status->warning(
'config-install-tables-exist' );
616 $conn->begin( __METHOD__ );
618 if ( !$conn->schemaExists( $schema ) ) {
619 $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-failed', $error );
631 if ( $error !==
true ) {
632 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
633 $conn->rollback( __METHOD__ );
634 $status->fatal(
'config-install-tables-manual-failed', $error );
636 $conn->commit( __METHOD__ );
640 if ( $status->isOK() ) {
649 return Status::newGood();
655 return array_merge( parent::getGlobalDefaults(), [
656 'wgDBmwschema' =>
'mediawiki',
664 if ( !$status->isOK() ) {
670 $conn = $status->value;
672 $exists = (bool)$conn->selectField(
'"pg_catalog"."pg_language"',
'1',
673 [
'lanname' =>
'plpgsql' ], __METHOD__ );
676 return Status::newGood();
681 $exists = (bool)$conn->selectField(
682 [
'"pg_catalog"."pg_class"',
'"pg_catalog"."pg_namespace"' ],
685 'pg_namespace.oid=relnamespace',
686 'nspname' =>
'pg_catalog',
687 'relname' =>
'pg_pltemplate',
692 $conn->query(
'CREATE LANGUAGE plpgsql', __METHOD__ );
694 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
697 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
700 return Status::newGood();
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...
Postgres database abstraction layer.
$wgDBuser
Config variable stub for the DBuser setting, for use by phpdoc and IDEs.
$wgDBpassword
Config variable stub for the DBpassword setting, for use by phpdoc and IDEs.
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s