aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--autoload.php9
-rw-r--r--includes/installer/ConnectionStatus.php23
-rw-r--r--includes/installer/DatabaseConnectForm.php71
-rw-r--r--includes/installer/DatabaseForm.php152
-rw-r--r--includes/installer/DatabaseInstaller.php255
-rw-r--r--includes/installer/DatabaseSettingsForm.php89
-rw-r--r--includes/installer/Installer.php3
-rw-r--r--includes/installer/MysqlConnectForm.php74
-rw-r--r--includes/installer/MysqlInstaller.php171
-rw-r--r--includes/installer/MysqlSettingsForm.php100
-rw-r--r--includes/installer/PostgresConnectForm.php104
-rw-r--r--includes/installer/PostgresInstaller.php216
-rw-r--r--includes/installer/PostgresSettingsForm.php96
-rw-r--r--includes/installer/SqliteConnectForm.php46
-rw-r--r--includes/installer/SqliteInstaller.php54
-rw-r--r--includes/installer/WebInstallerDBConnect.php4
-rw-r--r--includes/installer/WebInstallerDBSettings.php9
17 files changed, 832 insertions, 644 deletions
diff --git a/autoload.php b/autoload.php
index b3046a8b5335..0d06e43da5e6 100644
--- a/autoload.php
+++ b/autoload.php
@@ -1549,7 +1549,11 @@ $wgAutoloadLocalClasses = [
'MediaWiki\\Http\\MwHttpRequestToResponseInterfaceAdapter' => __DIR__ . '/includes/http/MwHttpRequestToResponseInterfaceAdapter.php',
'MediaWiki\\Http\\Telemetry' => __DIR__ . '/includes/http/Telemetry.php',
'MediaWiki\\Installer\\CliInstaller' => __DIR__ . '/includes/installer/CliInstaller.php',
+ 'MediaWiki\\Installer\\ConnectionStatus' => __DIR__ . '/includes/installer/ConnectionStatus.php',
+ 'MediaWiki\\Installer\\DatabaseConnectForm' => __DIR__ . '/includes/installer/DatabaseConnectForm.php',
+ 'MediaWiki\\Installer\\DatabaseForm' => __DIR__ . '/includes/installer/DatabaseForm.php',
'MediaWiki\\Installer\\DatabaseInstaller' => __DIR__ . '/includes/installer/DatabaseInstaller.php',
+ 'MediaWiki\\Installer\\DatabaseSettingsForm' => __DIR__ . '/includes/installer/DatabaseSettingsForm.php',
'MediaWiki\\Installer\\DatabaseUpdater' => __DIR__ . '/includes/installer/DatabaseUpdater.php',
'MediaWiki\\Installer\\Hook\\LoadExtensionSchemaUpdatesHook' => __DIR__ . '/includes/installer/Hook/LoadExtensionSchemaUpdatesHook.php',
'MediaWiki\\Installer\\InstallDocFormatter' => __DIR__ . '/includes/installer/InstallDocFormatter.php',
@@ -1558,11 +1562,16 @@ $wgAutoloadLocalClasses = [
'MediaWiki\\Installer\\InstallerOverrides' => __DIR__ . '/includes/installer/InstallerOverrides.php',
'MediaWiki\\Installer\\InstallerSessionProvider' => __DIR__ . '/includes/installer/InstallerSessionProvider.php',
'MediaWiki\\Installer\\LocalSettingsGenerator' => __DIR__ . '/includes/installer/LocalSettingsGenerator.php',
+ 'MediaWiki\\Installer\\MysqlConnectForm' => __DIR__ . '/includes/installer/MysqlConnectForm.php',
'MediaWiki\\Installer\\MysqlInstaller' => __DIR__ . '/includes/installer/MysqlInstaller.php',
+ 'MediaWiki\\Installer\\MysqlSettingsForm' => __DIR__ . '/includes/installer/MysqlSettingsForm.php',
'MediaWiki\\Installer\\MysqlUpdater' => __DIR__ . '/includes/installer/MysqlUpdater.php',
'MediaWiki\\Installer\\Pingback' => __DIR__ . '/includes/installer/Pingback.php',
+ 'MediaWiki\\Installer\\PostgresConnectForm' => __DIR__ . '/includes/installer/PostgresConnectForm.php',
'MediaWiki\\Installer\\PostgresInstaller' => __DIR__ . '/includes/installer/PostgresInstaller.php',
+ 'MediaWiki\\Installer\\PostgresSettingsForm' => __DIR__ . '/includes/installer/PostgresSettingsForm.php',
'MediaWiki\\Installer\\PostgresUpdater' => __DIR__ . '/includes/installer/PostgresUpdater.php',
+ 'MediaWiki\\Installer\\SqliteConnectForm' => __DIR__ . '/includes/installer/SqliteConnectForm.php',
'MediaWiki\\Installer\\SqliteInstaller' => __DIR__ . '/includes/installer/SqliteInstaller.php',
'MediaWiki\\Installer\\SqliteUpdater' => __DIR__ . '/includes/installer/SqliteUpdater.php',
'MediaWiki\\Installer\\WebInstaller' => __DIR__ . '/includes/installer/WebInstaller.php',
diff --git a/includes/installer/ConnectionStatus.php b/includes/installer/ConnectionStatus.php
new file mode 100644
index 000000000000..2e255f4204b4
--- /dev/null
+++ b/includes/installer/ConnectionStatus.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use Status;
+use Wikimedia\Rdbms\Database;
+
+/**
+ * @internal
+ */
+class ConnectionStatus extends Status {
+ public function __construct( Database $db = null ) {
+ $this->value = $db;
+ }
+
+ public function setDB( Database $db ) {
+ $this->value = $db;
+ }
+
+ public function getDB(): Database {
+ return $this->value;
+ }
+}
diff --git a/includes/installer/DatabaseConnectForm.php b/includes/installer/DatabaseConnectForm.php
new file mode 100644
index 000000000000..ccc3bb0dbaeb
--- /dev/null
+++ b/includes/installer/DatabaseConnectForm.php
@@ -0,0 +1,71 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Html\Html;
+use MediaWiki\Status\Status;
+
+/**
+ * @internal
+ */
+abstract class DatabaseConnectForm extends DatabaseForm {
+
+ /**
+ * Get HTML for a web form that configures this database. Configuration
+ * at this time should be the minimum needed to connect and test
+ * whether install or upgrade is required.
+ *
+ * If this is called, $this->parent can be assumed to be a WebInstaller.
+ */
+ abstract public function getHtml();
+
+ /**
+ * Set variables based on the request array, assuming it was submitted
+ * via the form returned by getConnectForm(). Validate the connection
+ * settings by attempting to connect with them.
+ *
+ * If this is called, $this->parent can be assumed to be a WebInstaller.
+ *
+ * @return Status
+ */
+ abstract public function submit();
+
+ /**
+ * Get a standard install-user fieldset.
+ *
+ * @return string
+ */
+ protected function getInstallUserBox() {
+ return "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
+ Html::element(
+ 'span',
+ [ 'class' => 'cdx-card__text__title' ],
+ wfMessage( 'config-db-install-account' )->text()
+ ) .
+ "<span class=\"cdx-card__text__description\">" .
+ $this->getTextBox(
+ '_InstallUser',
+ 'config-db-username',
+ [ 'dir' => 'ltr' ],
+ $this->webInstaller->getHelpBox( 'config-db-install-username' )
+ ) .
+ $this->getPasswordBox(
+ '_InstallPassword',
+ 'config-db-password',
+ [ 'dir' => 'ltr' ],
+ $this->webInstaller->getHelpBox( 'config-db-install-password' )
+ ) .
+ "</span></span></span>";
+ }
+
+ /**
+ * Submit a standard install user fieldset.
+ * @return Status
+ */
+ protected function submitInstallUserBox() {
+ $this->setVarsFromRequest( [ '_InstallUser', '_InstallPassword' ] );
+
+ return Status::newGood();
+ }
+
+}
diff --git a/includes/installer/DatabaseForm.php b/includes/installer/DatabaseForm.php
new file mode 100644
index 000000000000..ddbc8c5f1721
--- /dev/null
+++ b/includes/installer/DatabaseForm.php
@@ -0,0 +1,152 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+/**
+ * @internal
+ */
+abstract class DatabaseForm {
+ protected WebInstaller $webInstaller;
+ protected DatabaseInstaller $dbInstaller;
+
+ public function __construct( WebInstaller $webInstaller, DatabaseInstaller $dbInstaller ) {
+ $this->webInstaller = $webInstaller;
+ $this->dbInstaller = $dbInstaller;
+ }
+
+ /**
+ * Get a variable, taking local defaults into account.
+ * @param string $var
+ * @param mixed|null $default
+ * @return mixed
+ */
+ protected function getVar( $var, $default = null ) {
+ return $this->dbInstaller->getVar( $var, $default );
+ }
+
+ /**
+ * Set a variable
+ * @param string $name
+ * @param mixed $value
+ */
+ protected function setVar( $name, $value ) {
+ $this->dbInstaller->setVar( $name, $value );
+ }
+
+ /**
+ * Return the internal name, e.g. 'mysql', or 'sqlite'.
+ * @return string
+ */
+ protected function getName() {
+ return $this->dbInstaller->getName();
+ }
+
+ /**
+ * Get a labelled text box to configure a local variable.
+ *
+ * @param string $var
+ * @param string $label
+ * @param array $attribs
+ * @param string $helpData HTML
+ * @return string HTML
+ * @return-taint escaped
+ */
+ protected function getTextBox( $var, $label, $attribs = [], $helpData = "" ) {
+ $name = $this->getName() . '_' . $var;
+ $value = $this->getVar( $var );
+ if ( !isset( $attribs ) ) {
+ $attribs = [];
+ }
+
+ return $this->webInstaller->getTextBox( [
+ 'var' => $var,
+ 'label' => $label,
+ 'attribs' => $attribs,
+ 'controlName' => $name,
+ 'value' => $value,
+ 'help' => $helpData
+ ] );
+ }
+
+ /**
+ * Get a labelled password box to configure a local variable.
+ * Implements password hiding.
+ *
+ * @param string $var
+ * @param string $label
+ * @param array $attribs
+ * @param string $helpData HTML
+ * @return string HTML
+ * @return-taint escaped
+ */
+ protected function getPasswordBox( $var, $label, $attribs = [], $helpData = "" ) {
+ $name = $this->getName() . '_' . $var;
+ $value = $this->getVar( $var );
+ if ( !isset( $attribs ) ) {
+ $attribs = [];
+ }
+
+ return $this->webInstaller->getPasswordBox( [
+ 'var' => $var,
+ 'label' => $label,
+ 'attribs' => $attribs,
+ 'controlName' => $name,
+ 'value' => $value,
+ 'help' => $helpData
+ ] );
+ }
+
+ /**
+ * Get a labelled checkbox to configure a local boolean variable.
+ *
+ * @param string $var
+ * @param string $label
+ * @param array $attribs Optional.
+ * @param string $helpData Optional.
+ * @return string
+ */
+ protected function getCheckBox( $var, $label, $attribs = [], $helpData = "" ) {
+ $name = $this->getName() . '_' . $var;
+ $value = $this->getVar( $var );
+
+ return $this->webInstaller->getCheckBox( [
+ 'var' => $var,
+ 'label' => $label,
+ 'attribs' => $attribs,
+ 'controlName' => $name,
+ 'value' => $value,
+ 'help' => $helpData
+ ] );
+ }
+
+ /**
+ * Get a set of labelled radio buttons.
+ *
+ * @param array $params Parameters are:
+ * var: The variable to be configured (required)
+ * label: The message name for the label (required)
+ * itemLabelPrefix: The message name prefix for the item labels (required)
+ * values: List of allowed values (required)
+ * itemAttribs Array of attribute arrays, outer key is the value name (optional)
+ *
+ * @return string
+ */
+ protected function getRadioSet( $params ) {
+ $params['controlName'] = $this->getName() . '_' . $params['var'];
+ $params['value'] = $this->getVar( $params['var'] );
+
+ return $this->webInstaller->getRadioSet( $params );
+ }
+
+ /**
+ * Convenience function to set variables based on form data.
+ * Assumes that variables containing "password" in the name are (potentially
+ * fake) passwords.
+ * @param array $varNames
+ * @return array
+ */
+ protected function setVarsFromRequest( $varNames ) {
+ return $this->webInstaller->setVarsFromRequest( $varNames, $this->getName() . '_' );
+ }
+
+}
diff --git a/includes/installer/DatabaseInstaller.php b/includes/installer/DatabaseInstaller.php
index e680fdaba1ef..c8e319301765 100644
--- a/includes/installer/DatabaseInstaller.php
+++ b/includes/installer/DatabaseInstaller.php
@@ -25,7 +25,6 @@
namespace MediaWiki\Installer;
use Exception;
-use MediaWiki\Html\Html;
use MediaWiki\Status\Status;
use MWException;
use MWLBFactory;
@@ -49,7 +48,7 @@ abstract class DatabaseInstaller {
/**
* The Installer object.
*
- * @var WebInstaller
+ * @var Installer
*/
public $parent;
@@ -122,53 +121,12 @@ abstract class DatabaseInstaller {
}
/**
- * Get HTML for a web form that configures this database. Configuration
- * at this time should be the minimum needed to connect and test
- * whether install or upgrade is required.
- *
- * If this is called, $this->parent can be assumed to be a WebInstaller.
- */
- abstract public function getConnectForm();
-
- /**
- * Set variables based on the request array, assuming it was submitted
- * via the form returned by getConnectForm(). Validate the connection
- * settings by attempting to connect with them.
- *
- * If this is called, $this->parent can be assumed to be a WebInstaller.
- *
- * @return Status
- */
- abstract public function submitConnectForm();
-
- /**
- * Get HTML for a web form that retrieves settings used for installation.
- * $this->parent can be assumed to be a WebInstaller.
- * If the DB type has no settings beyond those already configured with
- * getConnectForm(), this should return false.
- * @return string|false
- */
- public function getSettingsForm() {
- return false;
- }
-
- /**
- * Set variables based on the request array, assuming it was submitted via
- * the form return by getSettingsForm().
- *
- * @return Status
- */
- public function submitSettingsForm() {
- return Status::newGood();
- }
-
- /**
* Open a connection to the database using the administrative user/password
* currently defined in the session, without any caching. Returns a status
* object. On success, the status object will contain a Database object in
* its value member.
*
- * @return Status
+ * @return ConnectionStatus
*/
abstract public function openConnection();
@@ -187,12 +145,11 @@ abstract class DatabaseInstaller {
*
* This will return a cached connection if one is available.
*
- * @return Status
- * @suppress PhanUndeclaredMethod
+ * @return ConnectionStatus
*/
public function getConnection() {
if ( $this->db ) {
- return Status::newGood( $this->db );
+ return new ConnectionStatus( $this->db );
}
$status = $this->openConnection();
@@ -375,8 +332,7 @@ abstract class DatabaseInstaller {
public function setupSchemaVars() {
$status = $this->getConnection();
if ( $status->isOK() ) {
- // @phan-suppress-next-line PhanUndeclaredMethod
- $status->value->setSchemaVars( $this->getSchemaVars() );
+ $status->getDB()->setSchemaVars( $this->getSchemaVars() );
} else {
$msg = __METHOD__ . ': unexpected error while establishing'
. ' a database connection with message: '
@@ -543,113 +499,9 @@ abstract class DatabaseInstaller {
$this->parent->setVar( $name, $value );
}
- /**
- * Get a labelled text box to configure a local variable.
- *
- * @param string $var
- * @param string $label
- * @param array $attribs
- * @param string $helpData HTML
- * @return string HTML
- * @return-taint escaped
- */
- public function getTextBox( $var, $label, $attribs = [], $helpData = "" ) {
- $name = $this->getName() . '_' . $var;
- $value = $this->getVar( $var );
- if ( !isset( $attribs ) ) {
- $attribs = [];
- }
+ abstract public function getConnectForm( WebInstaller $webInstaller ): DatabaseConnectForm;
- return $this->parent->getTextBox( [
- 'var' => $var,
- 'label' => $label,
- 'attribs' => $attribs,
- 'controlName' => $name,
- 'value' => $value,
- 'help' => $helpData
- ] );
- }
-
- /**
- * Get a labelled password box to configure a local variable.
- * Implements password hiding.
- *
- * @param string $var
- * @param string $label
- * @param array $attribs
- * @param string $helpData HTML
- * @return string HTML
- * @return-taint escaped
- */
- public function getPasswordBox( $var, $label, $attribs = [], $helpData = "" ) {
- $name = $this->getName() . '_' . $var;
- $value = $this->getVar( $var );
- if ( !isset( $attribs ) ) {
- $attribs = [];
- }
-
- return $this->parent->getPasswordBox( [
- 'var' => $var,
- 'label' => $label,
- 'attribs' => $attribs,
- 'controlName' => $name,
- 'value' => $value,
- 'help' => $helpData
- ] );
- }
-
- /**
- * Get a labelled checkbox to configure a local boolean variable.
- *
- * @param string $var
- * @param string $label
- * @param array $attribs Optional.
- * @param string $helpData Optional.
- * @return string
- */
- public function getCheckBox( $var, $label, $attribs = [], $helpData = "" ) {
- $name = $this->getName() . '_' . $var;
- $value = $this->getVar( $var );
-
- return $this->parent->getCheckBox( [
- 'var' => $var,
- 'label' => $label,
- 'attribs' => $attribs,
- 'controlName' => $name,
- 'value' => $value,
- 'help' => $helpData
- ] );
- }
-
- /**
- * Get a set of labelled radio buttons.
- *
- * @param array $params Parameters are:
- * var: The variable to be configured (required)
- * label: The message name for the label (required)
- * itemLabelPrefix: The message name prefix for the item labels (required)
- * values: List of allowed values (required)
- * itemAttribs Array of attribute arrays, outer key is the value name (optional)
- *
- * @return string
- */
- public function getRadioSet( $params ) {
- $params['controlName'] = $this->getName() . '_' . $params['var'];
- $params['value'] = $this->getVar( $params['var'] );
-
- return $this->parent->getRadioSet( $params );
- }
-
- /**
- * Convenience function to set variables based on form data.
- * Assumes that variables containing "password" in the name are (potentially
- * fake) passwords.
- * @param array $varNames
- * @return array
- */
- public function setVarsFromRequest( $varNames ) {
- return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' );
- }
+ abstract public function getSettingsForm( WebInstaller $webInstaller ): DatabaseSettingsForm;
/**
* Determine whether an existing installation of MediaWiki is present in
@@ -681,99 +533,6 @@ abstract class DatabaseInstaller {
}
/**
- * Get a standard install-user fieldset.
- *
- * @return string
- */
- public function getInstallUserBox() {
- return "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
- Html::element(
- 'span',
- [ 'class' => 'cdx-card__text__title' ],
- wfMessage( 'config-db-install-account' )->text()
- ) .
- "<span class=\"cdx-card__text__description\">" .
- $this->getTextBox(
- '_InstallUser',
- 'config-db-username',
- [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-install-username' )
- ) .
- $this->getPasswordBox(
- '_InstallPassword',
- 'config-db-password',
- [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-install-password' )
- ) .
- "</span></span></span>";
- }
-
- /**
- * Submit a standard install user fieldset.
- * @return Status
- */
- public function submitInstallUserBox() {
- $this->setVarsFromRequest( [ '_InstallUser', '_InstallPassword' ] );
-
- return Status::newGood();
- }
-
- /**
- * Get a standard web-user fieldset
- * @param string|false $noCreateMsg Message to display instead of the creation checkbox.
- * Set this to false to show a creation checkbox (default).
- *
- * @return string
- */
- public function getWebUserBox( $noCreateMsg = false ) {
- $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
- $s = "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
- Html::element(
- 'span',
- [ 'class' => 'cdx-card__text__title' ],
- wfMessage( 'config-db-web-account' )->text()
- ) .
- $this->getCheckBox(
- '_SameAccount', 'config-db-web-account-same',
- [ 'class' => 'hideShowRadio cdx-checkbox__input', 'rel' => 'dbOtherAccount' ]
- ) .
- Html::openElement( 'div', [ 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ] ) .
- $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
- $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
- $this->parent->getHelpBox( 'config-db-web-help' );
- if ( $noCreateMsg ) {
- $s .= Html::warningBox( wfMessage( $noCreateMsg )->plain(), 'config-warning-box' );
- } else {
- $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
- }
- $s .= Html::closeElement( 'div' ) . "</span></span></span>";
-
- return $s;
- }
-
- /**
- * Submit the form from getWebUserBox().
- *
- * @return Status
- */
- public function submitWebUserBox() {
- $this->setVarsFromRequest(
- [ 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount' ]
- );
-
- if ( $this->getVar( '_SameAccount' ) ) {
- $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
- $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
- }
-
- if ( $this->getVar( '_CreateDBAccount' ) && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
- return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
- }
-
- return Status::newGood();
- }
-
- /**
* Common function for databases that don't understand the MySQLish syntax of interwiki.list.
*
* @return Status
diff --git a/includes/installer/DatabaseSettingsForm.php b/includes/installer/DatabaseSettingsForm.php
new file mode 100644
index 000000000000..4ce3dcdf2e8e
--- /dev/null
+++ b/includes/installer/DatabaseSettingsForm.php
@@ -0,0 +1,89 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Html\Html;
+use MediaWiki\Status\Status;
+
+/**
+ * @internal
+ */
+class DatabaseSettingsForm extends DatabaseForm {
+
+ /**
+ * Get HTML for a web form that retrieves settings used for installation.
+ * $this->parent can be assumed to be a WebInstaller.
+ * If the DB type has no settings beyond those already configured with
+ * getConnectForm(), this should return false.
+ * @return string|false
+ */
+ public function getHtml() {
+ return false;
+ }
+
+ /**
+ * Set variables based on the request array, assuming it was submitted via
+ * the form return by getSettingsForm().
+ *
+ * @return Status
+ */
+ public function submit() {
+ return Status::newGood();
+ }
+
+ /**
+ * Get a standard web-user fieldset
+ * @param string|false $noCreateMsg Message to display instead of the creation checkbox.
+ * Set this to false to show a creation checkbox (default).
+ *
+ * @return string
+ */
+ protected function getWebUserBox( $noCreateMsg = false ) {
+ $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
+ $s = "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
+ Html::element(
+ 'span',
+ [ 'class' => 'cdx-card__text__title' ],
+ wfMessage( 'config-db-web-account' )->text()
+ ) .
+ $this->getCheckBox(
+ '_SameAccount', 'config-db-web-account-same',
+ [ 'class' => 'hideShowRadio cdx-checkbox__input', 'rel' => 'dbOtherAccount' ]
+ ) .
+ Html::openElement( 'div', [ 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ] ) .
+ $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
+ $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
+ $this->webInstaller->getHelpBox( 'config-db-web-help' );
+ if ( $noCreateMsg ) {
+ $s .= Html::warningBox( wfMessage( $noCreateMsg )->plain(), 'config-warning-box' );
+ } else {
+ $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
+ }
+ $s .= Html::closeElement( 'div' ) . "</span></span></span>";
+
+ return $s;
+ }
+
+ /**
+ * Submit the form from getWebUserBox().
+ *
+ * @return Status
+ */
+ public function submitWebUserBox() {
+ $this->setVarsFromRequest(
+ [ 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount' ]
+ );
+
+ if ( $this->getVar( '_SameAccount' ) ) {
+ $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
+ $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
+ }
+
+ if ( $this->getVar( '_CreateDBAccount' ) && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
+ return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
+ }
+
+ return Status::newGood();
+ }
+
+}
diff --git a/includes/installer/Installer.php b/includes/installer/Installer.php
index 1beb15d854f1..9f605e56191d 100644
--- a/includes/installer/Installer.php
+++ b/includes/installer/Installer.php
@@ -848,8 +848,7 @@ abstract class Installer {
if ( !$status->isOK() ) {
return $status;
}
- // @phan-suppress-next-line PhanUndeclaredMethod
- $status->value->insert(
+ $status->getDB()->insert(
'site_stats',
[
'ss_row_id' => 1,
diff --git a/includes/installer/MysqlConnectForm.php b/includes/installer/MysqlConnectForm.php
new file mode 100644
index 000000000000..08c24769f024
--- /dev/null
+++ b/includes/installer/MysqlConnectForm.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Html\Html;
+use MediaWiki\Status\Status;
+
+/**
+ * @internal
+ */
+class MysqlConnectForm extends DatabaseConnectForm {
+ /**
+ * @return string
+ */
+ public function getHtml() {
+ return $this->getTextBox(
+ 'wgDBserver',
+ 'config-db-host',
+ [],
+ $this->webInstaller->getHelpBox( 'config-db-host-help' )
+ ) .
+ $this->getCheckBox( 'wgDBssl', 'config-db-ssl' ) .
+ "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
+ Html::element(
+ 'span',
+ [ 'class' => 'cdx-card__text__title' ],
+ wfMessage( 'config-db-wiki-settings' )->text()
+ ) .
+ "<span class=\"cdx-card__text__description\">" .
+ $this->getTextBox( 'wgDBname', 'config-db-name', [ 'dir' => 'ltr' ],
+ $this->webInstaller->getHelpBox( 'config-db-name-help' ) ) .
+ $this->getTextBox( 'wgDBprefix', 'config-db-prefix', [ 'dir' => 'ltr' ],
+ $this->webInstaller->getHelpBox( 'config-db-prefix-help' ) ) .
+ "</span></span></span>" .
+ $this->getInstallUserBox();
+ }
+
+ public function submit() {
+ // Get variables from the request.
+ $newValues = $this->setVarsFromRequest( [ 'wgDBserver', 'wgDBname', 'wgDBprefix', 'wgDBssl' ] );
+
+ // Validate them.
+ $status = Status::newGood();
+ if ( !strlen( $newValues['wgDBserver'] ) ) {
+ $status->fatal( 'config-missing-db-host' );
+ }
+ if ( !strlen( $newValues['wgDBname'] ) ) {
+ $status->fatal( 'config-missing-db-name' );
+ } elseif ( !preg_match( '/^[a-z0-9+_-]+$/i', $newValues['wgDBname'] ) ) {
+ $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
+ }
+ if ( !preg_match( '/^[a-z0-9_-]*$/i', $newValues['wgDBprefix'] ) ) {
+ $status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
+ }
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ // Submit user box
+ $status = $this->submitInstallUserBox();
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ // Try to connect
+ $status = $this->dbInstaller->getConnection();
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ // Check version
+ return MysqlInstaller::meetsMinimumRequirement( $status->getDB() );
+ }
+}
diff --git a/includes/installer/MysqlInstaller.php b/includes/installer/MysqlInstaller.php
index 71f80a2c9f3a..ca6af464b1b5 100644
--- a/includes/installer/MysqlInstaller.php
+++ b/includes/installer/MysqlInstaller.php
@@ -24,10 +24,7 @@
namespace MediaWiki\Installer;
-use MediaWiki\Html\Html;
-use MediaWiki\MediaWikiServices;
use MediaWiki\Status\Status;
-use Wikimedia\Rdbms\Database;
use Wikimedia\Rdbms\DatabaseFactory;
use Wikimedia\Rdbms\DatabaseMySQL;
use Wikimedia\Rdbms\DBConnectionError;
@@ -89,72 +86,12 @@ class MysqlInstaller extends DatabaseInstaller {
return self::checkExtension( 'mysqli' );
}
- /**
- * @return string
- */
- public function getConnectForm() {
- return $this->getTextBox(
- 'wgDBserver',
- 'config-db-host',
- [],
- $this->parent->getHelpBox( 'config-db-host-help' )
- ) .
- $this->getCheckBox( 'wgDBssl', 'config-db-ssl' ) .
- "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
- Html::element(
- 'span',
- [ 'class' => 'cdx-card__text__title' ],
- wfMessage( 'config-db-wiki-settings' )->text()
- ) .
- "<span class=\"cdx-card__text__description\">" .
- $this->getTextBox( 'wgDBname', 'config-db-name', [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-name-help' ) ) .
- $this->getTextBox( 'wgDBprefix', 'config-db-prefix', [ 'dir' => 'ltr' ],
- $this->parent->getHelpBox( 'config-db-prefix-help' ) ) .
- "</span></span></span>" .
- $this->getInstallUserBox();
+ public function getConnectForm( WebInstaller $webInstaller ): DatabaseConnectForm {
+ return new MysqlConnectForm( $webInstaller, $this );
}
- public function submitConnectForm() {
- // Get variables from the request.
- $newValues = $this->setVarsFromRequest( [ 'wgDBserver', 'wgDBname', 'wgDBprefix', 'wgDBssl' ] );
-
- // Validate them.
- $status = Status::newGood();
- if ( !strlen( $newValues['wgDBserver'] ) ) {
- $status->fatal( 'config-missing-db-host' );
- }
- if ( !strlen( $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-missing-db-name' );
- } elseif ( !preg_match( '/^[a-z0-9+_-]+$/i', $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
- }
- if ( !preg_match( '/^[a-z0-9_-]*$/i', $newValues['wgDBprefix'] ) ) {
- $status->fatal( 'config-invalid-db-prefix', $newValues['wgDBprefix'] );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Submit user box
- $status = $this->submitInstallUserBox();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Try to connect
- $status = $this->getConnection();
- if ( !$status->isOK() ) {
- return $status;
- }
- /**
- * @var Database $conn
- */
- $conn = $status->value;
- '@phan-var Database $conn';
-
- // Check version
- return static::meetsMinimumRequirement( $conn );
+ public function getSettingsForm( WebInstaller $webInstaller ): DatabaseSettingsForm {
+ return new MysqlSettingsForm( $webInstaller, $this );
}
public static function meetsMinimumRequirement( IDatabase $conn ) {
@@ -166,10 +103,10 @@ class MysqlInstaller extends DatabaseInstaller {
}
/**
- * @return Status
+ * @return ConnectionStatus
*/
public function openConnection() {
- $status = Status::newGood();
+ $status = new ConnectionStatus;
try {
/** @var DatabaseMySQL $db */
$db = ( new DatabaseFactory() )->create( 'mysql', [
@@ -180,7 +117,7 @@ class MysqlInstaller extends DatabaseInstaller {
'dbname' => false,
'flags' => 0,
'tablePrefix' => $this->getVar( 'wgDBprefix' ) ] );
- $status->value = $db;
+ $status->setDB( $db );
} catch ( DBConnectionError $e ) {
$status->fatal( 'config-connection-error', $e->getMessage() );
}
@@ -197,10 +134,7 @@ class MysqlInstaller extends DatabaseInstaller {
return;
}
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$this->selectDatabase( $conn, $this->getVar( 'wgDBname' ) );
# Determine existing default character set
if ( $conn->tableExists( "revision", __METHOD__ ) ) {
@@ -260,11 +194,7 @@ class MysqlInstaller extends DatabaseInstaller {
*/
public function getEngines() {
$status = $this->getConnection();
-
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$engines = [];
$res = $conn->query( 'SHOW ENGINES', __METHOD__ );
@@ -297,8 +227,7 @@ class MysqlInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return false;
}
- /** @var Database $conn */
- $conn = $status->value;
+ $conn = $status->getDB();
// Get current account name
$currentName = $conn->selectField( '', 'CURRENT_USER()', '', __METHOD__ );
@@ -376,83 +305,6 @@ class MysqlInstaller extends DatabaseInstaller {
return "/$r/s";
}
- /**
- * @return string
- */
- public function getSettingsForm() {
- if ( $this->canCreateAccounts() ) {
- $noCreateMsg = false;
- } else {
- $noCreateMsg = 'config-db-web-no-create-privs';
- }
- $s = $this->getWebUserBox( $noCreateMsg );
-
- // Do engine selector
- $engines = $this->getEngines();
- // If the current default engine is not supported, use an engine that is
- if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
- $this->setVar( '_MysqlEngine', reset( $engines ) );
- }
-
- // If the current default charset is not supported, use a charset that is
- $charsets = $this->getCharsets();
- if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
- $this->setVar( '_MysqlCharset', reset( $charsets ) );
- }
-
- return $s;
- }
-
- /**
- * @return Status
- */
- public function submitSettingsForm() {
- $this->setVarsFromRequest( [ '_MysqlEngine', '_MysqlCharset' ] );
- $status = $this->submitWebUserBox();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // Validate the create checkbox
- $canCreate = $this->canCreateAccounts();
- if ( !$canCreate ) {
- $this->setVar( '_CreateDBAccount', false );
- $create = false;
- } else {
- $create = $this->getVar( '_CreateDBAccount' );
- }
-
- if ( !$create ) {
- // Test the web account
- try {
- MediaWikiServices::getInstance()->getDatabaseFactory()->create( 'mysql', [
- 'host' => $this->getVar( 'wgDBserver' ),
- 'user' => $this->getVar( 'wgDBuser' ),
- 'password' => $this->getVar( 'wgDBpassword' ),
- 'ssl' => $this->getVar( 'wgDBssl' ),
- 'dbname' => false,
- 'flags' => 0,
- 'tablePrefix' => $this->getVar( 'wgDBprefix' )
- ] );
- } catch ( DBConnectionError $e ) {
- return Status::newFatal( 'config-connection-error', $e->getMessage() );
- }
- }
-
- // Validate engines and charsets
- // This is done pre-submit already, so it's just for security
- $engines = $this->getEngines();
- if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
- $this->setVar( '_MysqlEngine', reset( $engines ) );
- }
- $charsets = $this->getCharsets();
- if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
- $this->setVar( '_MysqlCharset', reset( $charsets ) );
- }
-
- return Status::newGood();
- }
-
public function preInstall() {
# Add our user callback to installSteps, right before the tables are created.
$callback = [
@@ -470,8 +322,7 @@ class MysqlInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return $status;
}
- /** @var Database $conn */
- $conn = $status->value;
+ $conn = $status->getDB();
$dbName = $this->getVar( 'wgDBname' );
if ( !$this->databaseExists( $dbName ) ) {
$conn->query(
diff --git a/includes/installer/MysqlSettingsForm.php b/includes/installer/MysqlSettingsForm.php
new file mode 100644
index 000000000000..19f6727e5995
--- /dev/null
+++ b/includes/installer/MysqlSettingsForm.php
@@ -0,0 +1,100 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Status\Status;
+use Wikimedia\Rdbms\DBConnectionError;
+
+/**
+ * @internal
+ */
+class MysqlSettingsForm extends DatabaseSettingsForm {
+
+ /**
+ * @return string
+ */
+ public function getHtml() {
+ if ( $this->getMysqlInstaller()->canCreateAccounts() ) {
+ $noCreateMsg = false;
+ } else {
+ $noCreateMsg = 'config-db-web-no-create-privs';
+ }
+ $s = $this->getWebUserBox( $noCreateMsg );
+
+ // Do engine selector
+ $engines = $this->getMysqlInstaller()->getEngines();
+ // If the current default engine is not supported, use an engine that is
+ if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
+ $this->setVar( '_MysqlEngine', reset( $engines ) );
+ }
+
+ // If the current default charset is not supported, use a charset that is
+ $charsets = $this->getMysqlInstaller()->getCharsets();
+ if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
+ $this->setVar( '_MysqlCharset', reset( $charsets ) );
+ }
+
+ return $s;
+ }
+
+ /**
+ * @return Status
+ */
+ public function submit() {
+ $this->setVarsFromRequest( [ '_MysqlEngine', '_MysqlCharset' ] );
+ $status = $this->submitWebUserBox();
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ // Validate the create checkbox
+ $canCreate = $this->getMysqlInstaller()->canCreateAccounts();
+ if ( !$canCreate ) {
+ $this->setVar( '_CreateDBAccount', false );
+ $create = false;
+ } else {
+ $create = $this->getVar( '_CreateDBAccount' );
+ }
+
+ if ( !$create ) {
+ // Test the web account
+ try {
+ MediaWikiServices::getInstance()->getDatabaseFactory()->create( 'mysql', [
+ 'host' => $this->getVar( 'wgDBserver' ),
+ 'user' => $this->getVar( 'wgDBuser' ),
+ 'password' => $this->getVar( 'wgDBpassword' ),
+ 'ssl' => $this->getVar( 'wgDBssl' ),
+ 'dbname' => false,
+ 'flags' => 0,
+ 'tablePrefix' => $this->getVar( 'wgDBprefix' )
+ ] );
+ } catch ( DBConnectionError $e ) {
+ return Status::newFatal( 'config-connection-error', $e->getMessage() );
+ }
+ }
+
+ // Validate engines and charsets
+ // This is done pre-submit already, so it's just for security
+ $engines = $this->getMysqlInstaller()->getEngines();
+ if ( !in_array( $this->getVar( '_MysqlEngine' ), $engines ) ) {
+ $this->setVar( '_MysqlEngine', reset( $engines ) );
+ }
+ $charsets = $this->getMysqlInstaller()->getCharsets();
+ if ( !in_array( $this->getVar( '_MysqlCharset' ), $charsets ) ) {
+ $this->setVar( '_MysqlCharset', reset( $charsets ) );
+ }
+
+ return Status::newGood();
+ }
+
+ /**
+ * Downcast the DatabaseInstaller
+ * @return MysqlInstaller
+ */
+ private function getMysqlInstaller(): MysqlInstaller {
+ // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
+ return $this->dbInstaller;
+ }
+
+}
diff --git a/includes/installer/PostgresConnectForm.php b/includes/installer/PostgresConnectForm.php
new file mode 100644
index 000000000000..bbdc4579fe82
--- /dev/null
+++ b/includes/installer/PostgresConnectForm.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Html\Html;
+use MediaWiki\Status\Status;
+use Wikimedia\Rdbms\Database;
+
+/**
+ * @internal
+ */
+class PostgresConnectForm extends DatabaseConnectForm {
+
+ public function getHtml() {
+ return $this->getTextBox(
+ 'wgDBserver',
+ 'config-db-host',
+ [],
+ $this->webInstaller->getHelpBox( 'config-db-host-help' )
+ ) .
+ $this->getTextBox( 'wgDBport', 'config-db-port' ) .
+ $this->getCheckBox( 'wgDBssl', 'config-db-ssl' ) .
+ "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
+ Html::element(
+ 'span',
+ [ 'class' => 'cdx-card__text__title' ],
+ wfMessage( 'config-db-wiki-settings' )->text()
+ ) .
+ $this->getTextBox(
+ 'wgDBname',
+ 'config-db-name',
+ [],
+ $this->webInstaller->getHelpBox( 'config-db-name-help' )
+ ) .
+ $this->getTextBox(
+ 'wgDBmwschema',
+ 'config-db-schema',
+ [],
+ $this->webInstaller->getHelpBox( 'config-db-schema-help' )
+ ) .
+ "</span></span></span>" .
+ $this->getInstallUserBox();
+ }
+
+ public function submit() {
+ // Get variables from the request
+ $newValues = $this->setVarsFromRequest( [
+ 'wgDBserver',
+ 'wgDBport',
+ 'wgDBssl',
+ 'wgDBname',
+ 'wgDBmwschema'
+ ] );
+
+ // Validate them
+ $status = Status::newGood();
+ if ( !strlen( $newValues['wgDBname'] ) ) {
+ $status->fatal( 'config-missing-db-name' );
+ } elseif ( !preg_match( '/^[a-zA-Z0-9_]+$/', $newValues['wgDBname'] ) ) {
+ $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
+ }
+ if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBmwschema'] ) ) {
+ $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
+ }
+
+ // Submit user box
+ if ( $status->isOK() ) {
+ $status->merge( $this->submitInstallUserBox() );
+ }
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ $status = $this->getPostgresInstaller()->getPgConnection( 'create-db' );
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+ /**
+ * @var Database $conn
+ */
+ $conn = $status->value;
+
+ // Check version
+ $status = PostgresInstaller::meetsMinimumRequirement( $conn );
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
+ $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
+
+ return Status::newGood();
+ }
+
+ /**
+ * Downcast the DatabaseInstaller
+ * @return PostgresInstaller
+ */
+ private function getPostgresInstaller(): PostgresInstaller {
+ // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
+ return $this->dbInstaller;
+ }
+
+}
diff --git a/includes/installer/PostgresInstaller.php b/includes/installer/PostgresInstaller.php
index 21f69905b10a..e20a3d555690 100644
--- a/includes/installer/PostgresInstaller.php
+++ b/includes/installer/PostgresInstaller.php
@@ -24,7 +24,6 @@
namespace MediaWiki\Installer;
use InvalidArgumentException;
-use MediaWiki\Html\Html;
use MediaWiki\MediaWikiServices;
use MediaWiki\Status\Status;
use Wikimedia\Rdbms\Database;
@@ -59,6 +58,9 @@ class PostgresInstaller extends DatabaseInstaller {
protected static $notMinimumVersionMessage = 'config-postgres-old';
public $maxRoleSearchDepth = 5;
+ /**
+ * @var DatabasePostgres[]
+ */
protected $pgConns = [];
public function getName() {
@@ -69,85 +71,12 @@ class PostgresInstaller extends DatabaseInstaller {
return self::checkExtension( 'pgsql' );
}
- public function getConnectForm() {
- return $this->getTextBox(
- 'wgDBserver',
- 'config-db-host',
- [],
- $this->parent->getHelpBox( 'config-db-host-help' )
- ) .
- $this->getTextBox( 'wgDBport', 'config-db-port' ) .
- $this->getCheckBox( 'wgDBssl', 'config-db-ssl' ) .
- "<span class=\"cdx-card\"><span class=\"cdx-card__text\">" .
- Html::element(
- 'span',
- [ 'class' => 'cdx-card__text__title' ],
- wfMessage( 'config-db-wiki-settings' )->text()
- ) .
- $this->getTextBox(
- 'wgDBname',
- 'config-db-name',
- [],
- $this->parent->getHelpBox( 'config-db-name-help' )
- ) .
- $this->getTextBox(
- 'wgDBmwschema',
- 'config-db-schema',
- [],
- $this->parent->getHelpBox( 'config-db-schema-help' )
- ) .
- "</span></span></span>" .
- $this->getInstallUserBox();
+ public function getConnectForm( WebInstaller $webInstaller ): DatabaseConnectForm {
+ return new PostgresConnectForm( $webInstaller, $this );
}
- public function submitConnectForm() {
- // Get variables from the request
- $newValues = $this->setVarsFromRequest( [
- 'wgDBserver',
- 'wgDBport',
- 'wgDBssl',
- 'wgDBname',
- 'wgDBmwschema'
- ] );
-
- // Validate them
- $status = Status::newGood();
- if ( !strlen( $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-missing-db-name' );
- } elseif ( !preg_match( '/^[a-zA-Z0-9_]+$/', $newValues['wgDBname'] ) ) {
- $status->fatal( 'config-invalid-db-name', $newValues['wgDBname'] );
- }
- if ( !preg_match( '/^[a-zA-Z0-9_]*$/', $newValues['wgDBmwschema'] ) ) {
- $status->fatal( 'config-invalid-schema', $newValues['wgDBmwschema'] );
- }
-
- // Submit user box
- if ( $status->isOK() ) {
- $status->merge( $this->submitInstallUserBox() );
- }
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $status = $this->getPgConnection( 'create-db' );
- if ( !$status->isOK() ) {
- return $status;
- }
- /**
- * @var Database $conn
- */
- $conn = $status->value;
-
- // Check version
- $status = static::meetsMinimumRequirement( $conn );
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
- $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
-
- return Status::newGood();
+ public function getSettingsForm( WebInstaller $webInstaller ): DatabaseSettingsForm {
+ return new PostgresSettingsForm( $webInstaller, $this );
}
public function getConnection() {
@@ -169,10 +98,10 @@ class PostgresInstaller extends DatabaseInstaller {
* @param string $password
* @param string $dbName Database name
* @param string $schema Database schema
- * @return Status
+ * @return ConnectionStatus
*/
protected function openConnectionWithParams( $user, $password, $dbName, $schema ) {
- $status = Status::newGood();
+ $status = new ConnectionStatus;
try {
$db = MediaWikiServices::getInstance()->getDatabaseFactory()->create( 'postgres', [
'host' => $this->getVar( 'wgDBserver' ),
@@ -183,7 +112,7 @@ class PostgresInstaller extends DatabaseInstaller {
'dbname' => $dbName,
'schema' => $schema,
] );
- $status->value = $db;
+ $status->setDB( $db );
} catch ( DBConnectionError $e ) {
$status->fatal( 'config-connection-error', $e->getMessage() );
}
@@ -194,19 +123,16 @@ class PostgresInstaller extends DatabaseInstaller {
/**
* Get a special type of connection
* @param string $type See openPgConnection() for details.
- * @return Status
+ * @return ConnectionStatus
*/
- protected function getPgConnection( $type ) {
+ public function getPgConnection( $type ) {
if ( isset( $this->pgConns[$type] ) ) {
- return Status::newGood( $this->pgConns[$type] );
+ return new ConnectionStatus( $this->pgConns[$type] );
}
$status = $this->openPgConnection( $type );
if ( $status->isOK() ) {
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$conn->clearFlag( DBO_TRX );
$conn->commit( __METHOD__ );
$this->pgConns[$type] = $conn;
@@ -236,7 +162,7 @@ class PostgresInstaller extends DatabaseInstaller {
* - create-schema: A connection to the new DB, for creating schemas and
* other similar objects in the new DB.
* - create-tables: A connection with a role suitable for creating tables.
- * @return Status On success, a connection object will be in the value member.
+ * @return ConnectionStatus On success, a connection object will be in the value member.
*/
protected function openPgConnection( $type ) {
switch ( $type ) {
@@ -253,10 +179,7 @@ class PostgresInstaller extends DatabaseInstaller {
case 'create-tables':
$status = $this->openPgConnection( 'create-schema' );
if ( $status->isOK() ) {
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$safeRole = $conn->addIdentifierQuotes( $this->getVar( 'wgDBuser' ) );
$conn->query( "SET ROLE $safeRole", __METHOD__ );
}
@@ -276,7 +199,7 @@ class PostgresInstaller extends DatabaseInstaller {
array_unshift( $dbs, $this->getVar( 'wgDBname' ) );
}
$conn = false;
- $status = Status::newGood();
+ $status = new ConnectionStatus;
foreach ( $dbs as $db ) {
try {
$p = [
@@ -298,7 +221,7 @@ class PostgresInstaller extends DatabaseInstaller {
}
}
if ( $conn !== false ) {
- return Status::newGood( $conn );
+ return new ConnectionStatus( $conn );
} else {
return $status;
}
@@ -309,10 +232,7 @@ class PostgresInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return false;
}
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$superuser = $this->getVar( '_InstallUser' );
$row = $conn->selectRow( '"pg_catalog"."pg_roles"', '*',
@@ -321,7 +241,7 @@ class PostgresInstaller extends DatabaseInstaller {
return $row;
}
- protected function canCreateAccounts() {
+ public function canCreateAccounts() {
$perms = $this->getInstallUserPermissions();
return $perms && $perms->rolsuper || $perms->rolcreaterole;
}
@@ -331,85 +251,12 @@ class PostgresInstaller extends DatabaseInstaller {
return $perms && $perms->rolsuper;
}
- public function getSettingsForm() {
- if ( $this->canCreateAccounts() ) {
- $noCreateMsg = false;
- } else {
- $noCreateMsg = 'config-db-web-no-create-privs';
- }
- $s = $this->getWebUserBox( $noCreateMsg );
-
- return $s;
- }
-
- public function submitSettingsForm() {
- $status = $this->submitWebUserBox();
- if ( !$status->isOK() ) {
- return $status;
- }
-
- $same = $this->getVar( 'wgDBuser' ) === $this->getVar( '_InstallUser' );
-
- if ( $same ) {
- $exists = true;
- } else {
- // Check if the web user exists
- // Connect to the database with the install user
- $status = $this->getPgConnection( 'create-db' );
- if ( !$status->isOK() ) {
- return $status;
- }
- // @phan-suppress-next-line PhanUndeclaredMethod
- $exists = $status->value->roleExists( $this->getVar( 'wgDBuser' ) );
- }
-
- // Validate the create checkbox
- if ( $this->canCreateAccounts() && !$same && !$exists ) {
- $create = $this->getVar( '_CreateDBAccount' );
- } else {
- $this->setVar( '_CreateDBAccount', false );
- $create = false;
- }
-
- if ( !$create && !$exists ) {
- if ( $this->canCreateAccounts() ) {
- $msg = 'config-install-user-missing-create';
- } else {
- $msg = 'config-install-user-missing';
- }
-
- return Status::newFatal( $msg, $this->getVar( 'wgDBuser' ) );
- }
-
- if ( !$exists ) {
- // No more checks to do
- return Status::newGood();
- }
-
- // Existing web account. Test the connection.
- $status = $this->openConnectionToAnyDB(
- $this->getVar( 'wgDBuser' ),
- $this->getVar( 'wgDBpassword' ) );
- if ( !$status->isOK() ) {
- return $status;
- }
-
- // The web user is conventionally the table owner in PostgreSQL
- // installations. Make sure the install user is able to create
- // objects on behalf of the web user.
- if ( $same || $this->canCreateObjectsForWebUser() ) {
- return Status::newGood();
- } else {
- return Status::newFatal( 'config-pg-not-in-role' );
- }
- }
-
/**
* Returns true if the install user is able to create objects owned
* by the web user, false otherwise.
* @return bool
*/
- protected function canCreateObjectsForWebUser() {
+ public function canCreateObjectsForWebUser() {
if ( $this->isSuperUser() ) {
return true;
}
@@ -512,9 +359,8 @@ class PostgresInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return $status;
}
- /** @var DatabasePostgres $conn */
- $conn = $status->value;
- '@phan-var DatabasePostgres $conn';
+ $conn = $status->getDB();
+ '@phan-var DatabasePostgres $conn'; /** @var DatabasePostgres $conn */
// Create the schema if necessary
$schema = $this->getVar( 'wgDBmwschema' );
@@ -550,9 +396,8 @@ class PostgresInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return $status;
}
- /** @var DatabasePostgres $conn */
- $conn = $status->value;
- '@phan-var DatabasePostgres $conn';
+ $conn = $status->getDB();
+ '@phan-var DatabasePostgres $conn'; /** @var DatabasePostgres $conn */
$safeuser = $conn->addIdentifierQuotes( $this->getVar( 'wgDBuser' ) );
$safepass = $conn->addQuotes( $this->getVar( 'wgDBpassword' ) );
@@ -608,10 +453,8 @@ class PostgresInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return $status;
}
-
- /** @var DatabasePostgres $conn */
- $conn = $status->value;
- '@phan-var DatabasePostgres $conn';
+ $conn = $status->getDB();
+ '@phan-var DatabasePostgres $conn'; /** @var DatabasePostgres $conn */
if ( $conn->tableExists( 'archive', __METHOD__ ) ) {
$status->warning( 'config-install-tables-exist' );
@@ -671,10 +514,7 @@ class PostgresInstaller extends DatabaseInstaller {
if ( !$status->isOK() ) {
return $status;
}
- /**
- * @var Database $conn
- */
- $conn = $status->value;
+ $conn = $status->getDB();
$exists = (bool)$conn->selectField( '"pg_catalog"."pg_language"', '1',
[ 'lanname' => 'plpgsql' ], __METHOD__ );
diff --git a/includes/installer/PostgresSettingsForm.php b/includes/installer/PostgresSettingsForm.php
new file mode 100644
index 000000000000..370f893e1047
--- /dev/null
+++ b/includes/installer/PostgresSettingsForm.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Status\Status;
+use Wikimedia\Rdbms\DatabasePostgres;
+
+/**
+ * @internal
+ */
+class PostgresSettingsForm extends DatabaseSettingsForm {
+
+ public function getHtml() {
+ if ( $this->getPostgresInstaller()->canCreateAccounts() ) {
+ $noCreateMsg = false;
+ } else {
+ $noCreateMsg = 'config-db-web-no-create-privs';
+ }
+ $s = $this->getWebUserBox( $noCreateMsg );
+
+ return $s;
+ }
+
+ public function submit() {
+ $status = $this->submitWebUserBox();
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ $same = $this->getVar( 'wgDBuser' ) === $this->getVar( '_InstallUser' );
+
+ if ( $same ) {
+ $exists = true;
+ } else {
+ // Check if the web user exists
+ // Connect to the database with the install user
+ $status = $this->getPostgresInstaller()->getPgConnection( 'create-db' );
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+ $conn = $status->getDB();
+ '@phan-var DatabasePostgres $conn'; /** @var DatabasePostgres $conn */
+ $exists = $conn->roleExists( $this->getVar( 'wgDBuser' ) );
+ }
+
+ // Validate the create checkbox
+ if ( $this->getPostgresInstaller()->canCreateAccounts() && !$same && !$exists ) {
+ $create = $this->getVar( '_CreateDBAccount' );
+ } else {
+ $this->setVar( '_CreateDBAccount', false );
+ $create = false;
+ }
+
+ if ( !$create && !$exists ) {
+ if ( $this->getPostgresInstaller()->canCreateAccounts() ) {
+ $msg = 'config-install-user-missing-create';
+ } else {
+ $msg = 'config-install-user-missing';
+ }
+
+ return Status::newFatal( $msg, $this->getVar( 'wgDBuser' ) );
+ }
+
+ if ( !$exists ) {
+ // No more checks to do
+ return Status::newGood();
+ }
+
+ // Existing web account. Test the connection.
+ $status = $this->getPostgresInstaller()->openConnectionToAnyDB(
+ $this->getVar( 'wgDBuser' ),
+ $this->getVar( 'wgDBpassword' ) );
+ if ( !$status->isOK() ) {
+ return $status;
+ }
+
+ // The web user is conventionally the table owner in PostgreSQL
+ // installations. Make sure the install user is able to create
+ // objects on behalf of the web user.
+ if ( $same || $this->getPostgresInstaller()->canCreateObjectsForWebUser() ) {
+ return Status::newGood();
+ } else {
+ return Status::newFatal( 'config-pg-not-in-role' );
+ }
+ }
+
+ /**
+ * Downcast the DatabaseInstaller
+ * @return PostgresInstaller
+ */
+ private function getPostgresInstaller(): PostgresInstaller {
+ // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
+ return $this->dbInstaller;
+ }
+
+}
diff --git a/includes/installer/SqliteConnectForm.php b/includes/installer/SqliteConnectForm.php
new file mode 100644
index 000000000000..1eeedeeea1ef
--- /dev/null
+++ b/includes/installer/SqliteConnectForm.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace MediaWiki\Installer;
+
+use MediaWiki\Status\Status;
+
+/**
+ * @internal
+ */
+class SqliteConnectForm extends DatabaseConnectForm {
+
+ public function getHtml() {
+ return $this->getTextBox(
+ 'wgSQLiteDataDir',
+ 'config-sqlite-dir', [],
+ $this->webInstaller->getHelpBox( 'config-sqlite-dir-help' )
+ ) .
+ $this->getTextBox(
+ 'wgDBname',
+ 'config-db-name',
+ [],
+ $this->webInstaller->getHelpBox( 'config-sqlite-name-help' )
+ );
+ }
+
+ /**
+ * @return Status
+ */
+ public function submit() {
+ $this->setVarsFromRequest( [ 'wgSQLiteDataDir', 'wgDBname' ] );
+
+ # Try realpath() if the directory already exists
+ $dir = SqliteInstaller::realpath( $this->getVar( 'wgSQLiteDataDir' ) );
+ $result = SqliteInstaller::checkDataDir( $dir );
+ if ( $result->isOK() ) {
+ # Try expanding again in case we've just created it
+ $dir = SqliteInstaller::realpath( $dir );
+ $this->setVar( 'wgSQLiteDataDir', $dir );
+ }
+ # Table prefix is not used on SQLite, keep it empty
+ $this->setVar( 'wgDBprefix', '' );
+
+ return $result;
+ }
+
+}
diff --git a/includes/installer/SqliteInstaller.php b/includes/installer/SqliteInstaller.php
index 1d7dcda3967a..de553ae0747c 100644
--- a/includes/installer/SqliteInstaller.php
+++ b/includes/installer/SqliteInstaller.php
@@ -60,6 +60,14 @@ class SqliteInstaller extends DatabaseInstaller {
return self::checkExtension( 'pdo_sqlite' );
}
+ public function getConnectForm( WebInstaller $webInstaller ): DatabaseConnectForm {
+ return new SqliteConnectForm( $webInstaller, $this );
+ }
+
+ public function getSettingsForm( WebInstaller $webInstaller ): DatabaseSettingsForm {
+ return new DatabaseSettingsForm( $webInstaller, $this );
+ }
+
/**
* @return Status
*/
@@ -92,20 +100,6 @@ class SqliteInstaller extends DatabaseInstaller {
return $defaults;
}
- public function getConnectForm() {
- return $this->getTextBox(
- 'wgSQLiteDataDir',
- 'config-sqlite-dir', [],
- $this->parent->getHelpBox( 'config-sqlite-dir-help' )
- ) .
- $this->getTextBox(
- 'wgDBname',
- 'config-db-name',
- [],
- $this->parent->getHelpBox( 'config-sqlite-name-help' )
- );
- }
-
/**
* Safe wrapper for PHP's realpath() that fails gracefully if it's unable to canonicalize the path.
*
@@ -113,36 +107,16 @@ class SqliteInstaller extends DatabaseInstaller {
*
* @return string
*/
- private static function realpath( $path ) {
+ public static function realpath( $path ) {
return realpath( $path ) ?: $path;
}
/**
- * @return Status
- */
- public function submitConnectForm() {
- $this->setVarsFromRequest( [ 'wgSQLiteDataDir', 'wgDBname' ] );
-
- # Try realpath() if the directory already exists
- $dir = self::realpath( $this->getVar( 'wgSQLiteDataDir' ) );
- $result = self::checkDataDir( $dir );
- if ( $result->isOK() ) {
- # Try expanding again in case we've just created it
- $dir = self::realpath( $dir );
- $this->setVar( 'wgSQLiteDataDir', $dir );
- }
- # Table prefix is not used on SQLite, keep it empty
- $this->setVar( 'wgDBprefix', '' );
-
- return $result;
- }
-
- /**
* Check if the data directory is writable or can be created
* @param string $dir Path to the data directory
* @return Status Return fatal Status if $dir un-writable or no permission to create a directory
*/
- private static function checkDataDir( $dir ): Status {
+ public static function checkDataDir( $dir ): Status {
if ( is_dir( $dir ) ) {
if ( !is_readable( $dir ) ) {
return Status::newFatal( 'config-sqlite-dir-unwritable', $dir );
@@ -185,17 +159,17 @@ class SqliteInstaller extends DatabaseInstaller {
}
/**
- * @return Status
+ * @return ConnectionStatus
*/
public function openConnection() {
- $status = Status::newGood();
+ $status = new ConnectionStatus;
$dir = $this->getVar( 'wgSQLiteDataDir' );
$dbName = $this->getVar( 'wgDBname' );
try {
$db = MediaWikiServices::getInstance()->getDatabaseFactory()->create(
'sqlite', [ 'dbname' => $dbName, 'dbDirectory' => $dir ]
);
- $status->value = $db;
+ $status->setDB( $db );
} catch ( DBConnectionError $e ) {
$status->fatal( 'config-sqlite-connection-error', $e->getMessage() );
}
@@ -314,7 +288,7 @@ EOT;
// when the DB is being read and written concurrently.
// This causes the DB to be created in this mode
// so we only have to do this on creation.
- $mainConnStatus->value->query( "PRAGMA journal_mode=WAL", __METHOD__ );
+ $mainConnStatus->getDB()->query( "PRAGMA journal_mode=WAL", __METHOD__ );
return $mainConnStatus;
}
diff --git a/includes/installer/WebInstallerDBConnect.php b/includes/installer/WebInstallerDBConnect.php
index be54d08cf3c5..add5895c0238 100644
--- a/includes/installer/WebInstallerDBConnect.php
+++ b/includes/installer/WebInstallerDBConnect.php
@@ -98,7 +98,7 @@ class WebInstallerDBConnect extends WebInstallerPage {
]
) .
Html::element( 'h3', [], wfMessage( 'config-header-' . $type )->text() ) .
- $installer->getConnectForm() .
+ $installer->getConnectForm( $this->parent )->getHtml() .
"</div>\n";
}
@@ -126,7 +126,7 @@ class WebInstallerDBConnect extends WebInstallerPage {
return Status::newFatal( 'config-invalid-db-type' );
}
- return $installer->submitConnectForm();
+ return $installer->getConnectForm( $this->parent )->submit();
}
}
diff --git a/includes/installer/WebInstallerDBSettings.php b/includes/installer/WebInstallerDBSettings.php
index 1fd93811b393..b2cf463731c4 100644
--- a/includes/installer/WebInstallerDBSettings.php
+++ b/includes/installer/WebInstallerDBSettings.php
@@ -28,10 +28,11 @@ class WebInstallerDBSettings extends WebInstallerPage {
*/
public function execute() {
$installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) );
+ $form = $installer->getSettingsForm( $this->parent );
$r = $this->parent->request;
if ( $r->wasPosted() ) {
- $status = $installer->submitSettingsForm();
+ $status = $form->submit();
if ( $status === false ) {
return 'skip';
} elseif ( $status->isGood() ) {
@@ -41,13 +42,13 @@ class WebInstallerDBSettings extends WebInstallerPage {
}
}
- $form = $installer->getSettingsForm();
- if ( $form === false ) {
+ $formHtml = $form->getHtml();
+ if ( $formHtml === false ) {
return 'skip';
}
$this->startForm();
- $this->addHTML( $form );
+ $this->addHTML( $formHtml );
$this->endForm();
return null;