49 '_InstallUser' =>
'postgres',
71 $this->parent->getHelpBox(
'config-db-host-help' )
73 $this->
getTextBox(
'wgDBport',
'config-db-port' ) .
75 Html::openElement(
'fieldset' ) .
76 Html::element(
'legend', [],
wfMessage(
'config-db-wiki-settings' )->text() ) .
81 $this->parent->getHelpBox(
'config-db-name-help' )
87 $this->parent->getHelpBox(
'config-db-schema-help' )
89 Html::closeElement(
'fieldset' ) .
104 $status = Status::newGood();
105 if ( !strlen( $newValues[
'wgDBname'] ) ) {
106 $status->fatal(
'config-missing-db-name' );
107 } elseif ( !preg_match(
'/^[a-zA-Z0-9_]+$/', $newValues[
'wgDBname'] ) ) {
108 $status->fatal(
'config-invalid-db-name', $newValues[
'wgDBname'] );
110 if ( !preg_match(
'/^[a-zA-Z0-9_]*$/', $newValues[
'wgDBmwschema'] ) ) {
111 $status->fatal(
'config-invalid-schema', $newValues[
'wgDBmwschema'] );
115 if ( $status->isOK() ) {
118 if ( !$status->isOK() ) {
123 if ( !$status->isOK() ) {
129 $conn = $status->value;
132 $status = static::meetsMinimumRequirement( $conn );
133 if ( !$status->isOK() ) {
137 $this->
setVar(
'wgDBuser', $this->
getVar(
'_InstallUser' ) );
138 $this->
setVar(
'wgDBpassword', $this->
getVar(
'_InstallPassword' ) );
140 return Status::newGood();
145 if ( $status->isOK() ) {
146 $this->db = $status->value;
165 $status = Status::newGood();
167 $db = MediaWikiServices::getInstance()->getDatabaseFactory()->create(
'postgres', [
168 'host' => $this->
getVar(
'wgDBserver' ),
169 'port' => $this->
getVar(
'wgDBport' ),
171 'password' => $password,
172 'ssl' => $this->
getVar(
'wgDBssl' ),
176 $status->value =
$db;
178 $status->fatal(
'config-connection-error', $e->getMessage() );
190 if ( isset( $this->pgConns[
$type] ) ) {
191 return Status::newGood( $this->pgConns[
$type] );
195 if ( $status->isOK() ) {
199 $conn = $status->value;
201 $conn->commit( __METHOD__ );
202 $this->pgConns[
$type] = $conn;
237 $this->
getVar(
'_InstallUser' ),
238 $this->
getVar(
'_InstallPassword' ) );
239 case 'create-schema':
241 $this->
getVar(
'_InstallUser' ),
242 $this->
getVar(
'_InstallPassword' ),
243 $this->
getVar(
'wgDBname' ),
244 $this->
getVar(
'wgDBmwschema' ) );
245 case 'create-tables':
247 if ( $status->isOK() ) {
251 $conn = $status->value;
252 $safeRole = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
253 $conn->query(
"SET ROLE $safeRole", __METHOD__ );
258 throw new MWException(
"Invalid special connection type: \"$type\"" );
267 if ( !in_array( $this->
getVar(
'wgDBname' ), $dbs ) ) {
268 array_unshift( $dbs, $this->
getVar(
'wgDBname' ) );
271 $status = Status::newGood();
272 foreach ( $dbs as
$db ) {
275 'host' => $this->
getVar(
'wgDBserver' ),
276 'port' => $this->
getVar(
'wgDBport' ),
278 'password' => $password,
279 'ssl' => $this->
getVar(
'wgDBssl' ),
282 $conn = Database::factory(
'postgres', $p );
285 $status->fatal(
'config-pg-test-error',
$db,
286 $error->getMessage() );
288 if ( $conn !==
false ) {
292 if ( $conn !==
false ) {
293 return Status::newGood( $conn );
301 if ( !$status->isOK() ) {
307 $conn = $status->value;
308 $superuser = $this->
getVar(
'_InstallUser' );
310 $row = $conn->selectRow(
'"pg_catalog"."pg_roles"',
'*',
311 [
'rolname' => $superuser ], __METHOD__ );
322 return $perms->rolsuper ===
't' || $perms->rolcreaterole ===
't';
331 return $perms->rolsuper ===
't';
336 $noCreateMsg =
false;
338 $noCreateMsg =
'config-db-web-no-create-privs';
347 if ( !$status->isOK() ) {
351 $same = $this->
getVar(
'wgDBuser' ) === $this->
getVar(
'_InstallUser' );
359 if ( !$status->isOK() ) {
363 $exists = $status->value->roleExists( $this->
getVar(
'wgDBuser' ) );
368 $create = $this->
getVar(
'_CreateDBAccount' );
370 $this->
setVar(
'_CreateDBAccount',
false );
374 if ( !$create && !$exists ) {
376 $msg =
'config-install-user-missing-create';
378 $msg =
'config-install-user-missing';
381 return Status::newFatal( $msg, $this->
getVar(
'wgDBuser' ) );
386 return Status::newGood();
391 $this->
getVar(
'wgDBuser' ),
392 $this->
getVar(
'wgDBpassword' ) );
393 if ( !$status->isOK() ) {
401 return Status::newGood();
403 return Status::newFatal(
'config-pg-not-in-role' );
418 if ( !$status->isOK() ) {
421 $conn = $status->value;
422 $installerId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
423 [
'rolname' => $this->
getVar(
'_InstallUser' ) ], __METHOD__ );
424 $webId = $conn->selectField(
'"pg_catalog"."pg_roles"',
'oid',
425 [
'rolname' => $this->
getVar(
'wgDBuser' ) ], __METHOD__ );
427 return $this->
isRoleMember( $conn, $installerId, $webId, $this->maxRoleSearchDepth );
438 protected function isRoleMember( $conn, $targetMember, $group, $maxDepth ) {
439 if ( $targetMember === $group ) {
444 $res = $conn->select(
'"pg_catalog"."pg_auth_members"', [
'member' ],
445 [
'roleid' => $group ], __METHOD__ );
446 foreach (
$res as $row ) {
447 if ( $row->member == $targetMember ) {
453 if ( $maxDepth > 0 &&
454 $this->
isRoleMember( $conn, $targetMember, $row->member, $maxDepth - 1 )
467 'callback' => [ $this,
'setupUser' ],
470 'name' =>
'pg-commit',
471 'callback' => [ $this,
'commitChanges' ],
474 'name' =>
'pg-plpgsql',
475 'callback' => [ $this,
'setupPLpgSQL' ],
479 'callback' => [ $this,
'setupSchema' ]
482 if ( $this->
getVar(
'_CreateDBAccount' ) ) {
483 $this->parent->addInstallStep( $createDbAccount,
'database' );
485 $this->parent->addInstallStep( $commitCB,
'interwiki' );
486 $this->parent->addInstallStep( $plpgCB,
'database' );
487 $this->parent->addInstallStep( $schemaCB,
'database' );
492 if ( !$status->isOK() ) {
495 $conn = $status->value;
497 $dbName = $this->
getVar(
'wgDBname' );
499 $exists = (bool)$conn->selectField(
'"pg_catalog"."pg_database"',
'1',
500 [
'datname' => $dbName ], __METHOD__ );
502 $safedb = $conn->addIdentifierQuotes( $dbName );
503 $conn->query(
"CREATE DATABASE $safedb", __METHOD__ );
506 return Status::newGood();
512 if ( !$status->isOK() ) {
516 $conn = $status->value;
517 '@phan-var DatabasePostgres $conn';
520 $schema = $this->
getVar(
'wgDBmwschema' );
521 $safeschema = $conn->addIdentifierQuotes( $schema );
522 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
523 if ( !$conn->schemaExists( $schema ) ) {
525 $conn->query(
"CREATE SCHEMA $safeschema AUTHORIZATION $safeuser", __METHOD__ );
527 return Status::newFatal(
'config-install-pg-schema-failed',
528 $this->
getVar(
'_InstallUser' ), $schema );
533 $conn->determineCoreSchema( $schema );
535 return Status::newGood();
539 $this->db->commit( __METHOD__ );
541 return Status::newGood();
545 if ( !$this->
getVar(
'_CreateDBAccount' ) ) {
546 return Status::newGood();
550 if ( !$status->isOK() ) {
554 $conn = $status->value;
555 '@phan-var DatabasePostgres $conn';
557 $safeuser = $conn->addIdentifierQuotes( $this->
getVar(
'wgDBuser' ) );
558 $safepass = $conn->addQuotes( $this->
getVar(
'wgDBpassword' ) );
561 $userExists = $conn->roleExists( $this->
getVar(
'wgDBuser' ) );
562 if ( !$userExists ) {
565 $sql =
"CREATE ROLE $safeuser NOCREATEDB LOGIN PASSWORD $safepass";
571 $sql .=
' ROLE' . $conn->addIdentifierQuotes( $this->
getVar(
'_InstallUser' ) );
574 $conn->query( $sql, __METHOD__ );
576 return Status::newFatal(
'config-install-user-create-failed',
577 $this->
getVar(
'wgDBuser' ), $e->getMessage() );
581 return Status::newGood();
585 $port = $this->
getVar(
'wgDBport' );
586 $useSsl = $this->
getVar(
'wgDBssl' ) ?
'true' :
'false';
587 $schema = $this->
getVar(
'wgDBmwschema' );
589 return "# Postgres specific settings
590\$wgDBport = \"{$port}\";
591\$wgDBssl = {$useSsl};
592\$wgDBmwschema = \"{$schema}\";";
598 # Normal user and password are selected after this step, so for now
599 # just copy these two
601 $wgDBpassword = $this->
getVar(
'_InstallPassword' );
605 $schema = $this->
getVar(
'wgDBmwschema' );
608 if ( !$status->isOK() ) {
613 $conn = $status->value;
614 '@phan-var DatabasePostgres $conn';
616 if ( $conn->tableExists(
'archive', __METHOD__ ) ) {
617 $status->warning(
'config-install-tables-exist' );
623 $conn->begin( __METHOD__ );
625 if ( !$conn->schemaExists( $schema ) ) {
626 $status->fatal(
'config-install-pg-schema-not-exist' );
632 if ( $error !==
true ) {
633 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
634 $conn->rollback( __METHOD__ );
635 $status->fatal(
'config-install-tables-failed', $error );
638 if ( $error !==
true ) {
639 $conn->reportQueryError( $error, 0,
'', __METHOD__ );
640 $conn->rollback( __METHOD__ );
641 $status->fatal(
'config-install-tables-manual-failed', $error );
643 $conn->commit( __METHOD__ );
647 if ( $status->isOK() ) {
656 return Status::newGood();
662 return array_merge( parent::getGlobalDefaults(), [
663 'wgDBmwschema' =>
'mediawiki',
671 if ( !$status->isOK() ) {
677 $conn = $status->value;
679 $exists = (bool)$conn->selectField(
'"pg_catalog"."pg_language"',
'1',
680 [
'lanname' =>
'plpgsql' ], __METHOD__ );
683 return Status::newGood();
688 $exists = (bool)$conn->selectField(
689 [
'"pg_catalog"."pg_class"',
'"pg_catalog"."pg_namespace"' ],
692 'pg_namespace.oid=relnamespace',
693 'nspname' =>
'pg_catalog',
694 'relname' =>
'pg_pltemplate',
699 $conn->query(
'CREATE LANGUAGE plpgsql', __METHOD__ );
701 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
704 return Status::newFatal(
'config-pg-no-plpgsql', $this->
getVar(
'wgDBname' ) );
707 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.
getCheckBox( $var, $label, $attribs=[], $helpData="")
Get a labelled checkbox to configure a local boolean variable.
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