X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Finstaller%2FDatabaseInstaller.php;h=0beedfa462bf03856242525fab090197e259f60d;hb=392af46809d831514f49618cdef1e1529d7fddf4;hp=6c4c5527a5b5c30f0fd4587097a48915860840f6;hpb=a5053d4c5ad87796864a7030370be19ea44e923c;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/installer/DatabaseInstaller.php b/includes/installer/DatabaseInstaller.php index 6c4c5527a5..0beedfa462 100644 --- a/includes/installer/DatabaseInstaller.php +++ b/includes/installer/DatabaseInstaller.php @@ -2,6 +2,21 @@ /** * DBMS-specific installation helper. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * * @file * @ingroup Deployment */ @@ -19,7 +34,7 @@ abstract class DatabaseInstaller { * * TODO: naming this parent is confusing, 'installer' would be clearer. * - * @var Installer + * @var WebInstaller */ public $parent; @@ -50,10 +65,19 @@ abstract class DatabaseInstaller { public abstract function getName(); /** - * @return true if the client library is compiled in. + * @return bool Returns true if the client library is compiled in. */ public abstract function isCompiled(); + /** + * Checks for installation prerequisites other than those checked by isCompiled() + * @since 1.19 + * @return Status + */ + public function checkPrerequisites() { + return Status::newGood(); + } + /** * Get HTML for a web form that configures this database. Configuration * at this time should be the minimum needed to connect and test @@ -79,6 +103,7 @@ abstract class DatabaseInstaller { * $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 bool */ public function getSettingsForm() { return false; @@ -95,14 +120,14 @@ abstract class DatabaseInstaller { } /** - * Connect to the database using the administrative user/password currently - * defined in the session. On success, return the connection, on failure, - * - * This may be called multiple times, so the result should be cached. + * 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 */ - public abstract function getConnection(); + public abstract function openConnection(); /** * Create the database and return a Status object indicating success or @@ -112,6 +137,30 @@ abstract class DatabaseInstaller { */ public abstract function setupDatabase(); + /** + * Connect to the database using the administrative user/password currently + * defined in the session. Returns a status object. On success, the status + * object will contain a Database object in its value member. + * + * This will return a cached connection if one is available. + * + * @return Status + */ + public function getConnection() { + if ( $this->db ) { + return Status::newGood( $this->db ); + } + + $status = $this->openConnection(); + if ( $status->isOK() ) { + $this->db = $status->value; + // Enable autocommit + $this->db->clearFlag( DBO_TRX ); + $this->db->commit( __METHOD__ ); + } + return $status; + } + /** * Create database tables from scratch. * @@ -124,15 +173,16 @@ abstract class DatabaseInstaller { } $this->db->selectDB( $this->getVar( 'wgDBname' ) ); - if( $this->db->tableExists( 'user' ) ) { + if( $this->db->tableExists( 'archive', __METHOD__ ) ) { $status->warning( 'config-install-tables-exist' ); + $this->enableLB(); return $status; } $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files $this->db->begin( __METHOD__ ); - $error = $this->db->sourceFile( $this->db->getSchema() ); + $error = $this->db->sourceFile( $this->db->getSchemaPath() ); if( $error !== true ) { $this->db->reportQueryError( $error, 0, '', __METHOD__ ); $this->db->rollback( __METHOD__ ); @@ -142,11 +192,27 @@ abstract class DatabaseInstaller { } // Resume normal operations if( $status->isOk() ) { - LBFactory::enableBackend(); + $this->enableLB(); } return $status; } + /** + * Create the tables for each extension the user enabled + * @return Status + */ + public function createExtensionTables() { + $status = $this->getConnection(); + if ( !$status->isOK() ) { + return $status; + } + + // Now run updates to create tables for old extensions + DatabaseUpdater::newForDB( $this->db )->doUpdates( array( 'extensions' ) ); + + return $status; + } + /** * Get the DBMS-specific options for LocalSettings.php generation. * @@ -154,14 +220,52 @@ abstract class DatabaseInstaller { */ public abstract function getLocalSettings(); + /** + * Override this to provide DBMS-specific schema variables, to be + * substituted into tables.sql and other schema files. + * @return array + */ + public function getSchemaVars() { + return array(); + } + + /** + * Set appropriate schema variables in the current database connection. + * + * This should be called after any request data has been imported, but before + * any write operations to the database. + */ + public function setupSchemaVars() { + $status = $this->getConnection(); + if ( $status->isOK() ) { + $status->value->setSchemaVars( $this->getSchemaVars() ); + } else { + throw new MWException( __METHOD__.': unexpected DB connection error' ); + } + } + + /** + * Set up LBFactory so that wfGetDB() etc. works. + * We set up a special LBFactory instance which returns the current + * installer connection. + */ + public function enableLB() { + $status = $this->getConnection(); + if ( !$status->isOK() ) { + throw new MWException( __METHOD__.': unexpected DB connection error' ); + } + LBFactory::setInstance( new LBFactory_Single( array( + 'connection' => $status->value ) ) ); + } + /** * Perform database upgrades * * @return Boolean */ public function doUpgrade() { - # Maintenance scripts like wfGetDB() - LBFactory::enableBackend(); + $this->setupSchemaVars(); + $this->enableLB(); $ret = true; ob_start( array( $this, 'outputHandler' ) ); @@ -169,7 +273,7 @@ abstract class DatabaseInstaller { $up = DatabaseUpdater::newForDB( $this->db ); $up->doUpdates(); } catch ( MWException $e ) { - echo "\nAn error occured:\n"; + echo "\nAn error occurred:\n"; echo $e->getText(); $ret = false; } @@ -195,24 +299,16 @@ abstract class DatabaseInstaller { /** * Get an array of MW configuration globals that will be configured by this class. + * @return array */ public function getGlobalNames() { return $this->globalNames; } - /** - * Return any table options to be applied to all tables that don't - * override them. - * - * @return Array - */ - public function getTableOptions() { - return array(); - } - /** * Construct and initialise parent. * This is typically only called from Installer::getDBInstaller() + * @param $parent */ public function __construct( $parent ) { $this->parent = $parent; @@ -223,6 +319,8 @@ abstract class DatabaseInstaller { * Check if a named extension is present. * * @see wfDl + * @param $name + * @return bool */ protected static function checkExtension( $name ) { wfSuppressWarnings(); @@ -233,6 +331,7 @@ abstract class DatabaseInstaller { /** * Get the internationalised name for this DBMS. + * @return String */ public function getReadableName() { return wfMsg( 'config-type-' . $this->getName() ); @@ -241,6 +340,7 @@ abstract class DatabaseInstaller { /** * Get a name=>value map of MW configuration globals that overrides. * DefaultSettings.php + * @return array */ public function getGlobalDefaults() { return array(); @@ -248,6 +348,7 @@ abstract class DatabaseInstaller { /** * Get a name=>value map of internal variables used during installation. + * @return array */ public function getInternalDefaults() { return $this->internalDefaults; @@ -255,6 +356,9 @@ abstract class DatabaseInstaller { /** * Get a variable, taking local defaults into account. + * @param $var string + * @param $default null + * @return mixed */ public function getVar( $var, $default = null ) { $defaults = $this->getGlobalDefaults(); @@ -269,6 +373,8 @@ abstract class DatabaseInstaller { /** * Convenience alias for $this->parent->setVar() + * @param $name string + * @param $value mixed */ public function setVar( $name, $value ) { $this->parent->setVar( $name, $value ); @@ -276,6 +382,12 @@ abstract class DatabaseInstaller { /** * Get a labelled text box to configure a local variable. + * + * @param $var string + * @param $label string + * @param $attribs array + * @param $helpData string + * @return string */ public function getTextBox( $var, $label, $attribs = array(), $helpData = "" ) { $name = $this->getName() . '_' . $var; @@ -296,6 +408,12 @@ abstract class DatabaseInstaller { /** * Get a labelled password box to configure a local variable. * Implements password hiding. + * + * @param $var string + * @param $label string + * @param $attribs array + * @param $helpData string + * @return string */ public function getPasswordBox( $var, $label, $attribs = array(), $helpData = "" ) { $name = $this->getName() . '_' . $var; @@ -315,6 +433,8 @@ abstract class DatabaseInstaller { /** * Get a labelled checkbox to configure a local boolean variable. + * + * @return string */ public function getCheckBox( $var, $label, $attribs = array(), $helpData = "" ) { $name = $this->getName() . '_' . $var; @@ -340,6 +460,7 @@ abstract class DatabaseInstaller { * 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']; @@ -352,6 +473,7 @@ abstract class DatabaseInstaller { * Assumes that variables containing "password" in the name are (potentially * fake) passwords. * @param $varNames Array + * @return array */ public function setVarsFromRequest( $varNames ) { return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' ); @@ -376,23 +498,26 @@ abstract class DatabaseInstaller { if ( !$this->db->selectDB( $this->getVar( 'wgDBname' ) ) ) { return false; } - return $this->db->tableExists( 'cur' ) || $this->db->tableExists( 'revision' ); + return $this->db->tableExists( 'cur', __METHOD__ ) || $this->db->tableExists( 'revision', __METHOD__ ); } /** * Get a standard install-user fieldset. + * + * @return String */ public function getInstallUserBox() { return Html::openElement( 'fieldset' ) . Html::element( 'legend', array(), wfMsg( 'config-db-install-account' ) ) . - $this->getTextBox( '_InstallUser', 'config-db-username', array(), $this->parent->getHelpBox( 'config-db-install-username' ) ) . - $this->getPasswordBox( '_InstallPassword', 'config-db-password', array(), $this->parent->getHelpBox( 'config-db-install-password' ) ) . + $this->getTextBox( '_InstallUser', 'config-db-username', array( 'dir' => 'ltr' ), $this->parent->getHelpBox( 'config-db-install-username' ) ) . + $this->getPasswordBox( '_InstallPassword', 'config-db-password', array( 'dir' => 'ltr' ), $this->parent->getHelpBox( 'config-db-install-password' ) ) . Html::closeElement( 'fieldset' ); } /** * Submit a standard install user fieldset. + * @return Status */ public function submitInstallUserBox() { $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword' ) ); @@ -403,15 +528,18 @@ abstract class DatabaseInstaller { * Get a standard web-user fieldset * @param $noCreateMsg String: Message to display instead of the creation checkbox. * Set this to false to show a creation checkbox. + * + * @return String */ public function getWebUserBox( $noCreateMsg = false ) { + $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : ''; $s = Html::openElement( 'fieldset' ) . Html::element( 'legend', array(), wfMsg( 'config-db-web-account' ) ) . $this->getCheckBox( '_SameAccount', 'config-db-web-account-same', array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' ) ) . - Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => 'display: none;' ) ) . + Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) . $this->getTextBox( 'wgDBuser', 'config-db-username' ) . $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) . $this->parent->getHelpBox( 'config-db-web-help' ); @@ -439,11 +567,17 @@ abstract class DatabaseInstaller { $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.sql. + * + * @return Status */ public function populateInterwikiTable() { $status = $this->getConnection(); @@ -457,11 +591,13 @@ abstract class DatabaseInstaller { return $status; } global $IP; + wfSuppressWarnings(); $rows = file( "$IP/maintenance/interwiki.list", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ); + wfRestoreWarnings(); $interwikis = array(); if ( !$rows ) { - return Status::newFatal( 'config-install-interwiki-sql' ); + return Status::newFatal( 'config-install-interwiki-list' ); } foreach( $rows as $row ) { $row = preg_replace( '/^\s*([^#]*?)\s*(#.*)?$/', '\\1', $row ); // strip comments - whee