MediaWiki  REL1_22
DatabaseInstaller.php
Go to the documentation of this file.
00001 <?php
00030 abstract class DatabaseInstaller {
00031 
00039     public $parent;
00040 
00046     public $db = null;
00047 
00053     protected $internalDefaults = array();
00054 
00060     protected $globalNames = array();
00061 
00065     abstract public function getName();
00066 
00070     abstract public function isCompiled();
00071 
00077     public function checkPrerequisites() {
00078         return Status::newGood();
00079     }
00080 
00088     abstract public function getConnectForm();
00089 
00099     abstract public function submitConnectForm();
00100 
00108     public function getSettingsForm() {
00109         return false;
00110     }
00111 
00118     public function submitSettingsForm() {
00119         return Status::newGood();
00120     }
00121 
00130     abstract public function openConnection();
00131 
00138     abstract public function setupDatabase();
00139 
00149     public function getConnection() {
00150         if ( $this->db ) {
00151             return Status::newGood( $this->db );
00152         }
00153 
00154         $status = $this->openConnection();
00155         if ( $status->isOK() ) {
00156             $this->db = $status->value;
00157             // Enable autocommit
00158             $this->db->clearFlag( DBO_TRX );
00159             $this->db->commit( __METHOD__ );
00160         }
00161 
00162         return $status;
00163     }
00164 
00170     public function createTables() {
00171         $status = $this->getConnection();
00172         if ( !$status->isOK() ) {
00173             return $status;
00174         }
00175         $this->db->selectDB( $this->getVar( 'wgDBname' ) );
00176 
00177         if ( $this->db->tableExists( 'archive', __METHOD__ ) ) {
00178             $status->warning( 'config-install-tables-exist' );
00179             $this->enableLB();
00180 
00181             return $status;
00182         }
00183 
00184         $this->db->setFlag( DBO_DDLMODE ); // For Oracle's handling of schema files
00185         $this->db->begin( __METHOD__ );
00186 
00187         $error = $this->db->sourceFile( $this->db->getSchemaPath() );
00188         if ( $error !== true ) {
00189             $this->db->reportQueryError( $error, 0, '', __METHOD__ );
00190             $this->db->rollback( __METHOD__ );
00191             $status->fatal( 'config-install-tables-failed', $error );
00192         } else {
00193             $this->db->commit( __METHOD__ );
00194         }
00195         // Resume normal operations
00196         if ( $status->isOk() ) {
00197             $this->enableLB();
00198         }
00199 
00200         return $status;
00201     }
00202 
00207     public function createExtensionTables() {
00208         $status = $this->getConnection();
00209         if ( !$status->isOK() ) {
00210             return $status;
00211         }
00212 
00213         // Now run updates to create tables for old extensions
00214         DatabaseUpdater::newForDB( $this->db )->doUpdates( array( 'extensions' ) );
00215 
00216         return $status;
00217     }
00218 
00224     abstract public function getLocalSettings();
00225 
00231     public function getSchemaVars() {
00232         return array();
00233     }
00234 
00241     public function setupSchemaVars() {
00242         $status = $this->getConnection();
00243         if ( $status->isOK() ) {
00244             $status->value->setSchemaVars( $this->getSchemaVars() );
00245         } else {
00246             throw new MWException( __METHOD__ . ': unexpected DB connection error' );
00247         }
00248     }
00249 
00255     public function enableLB() {
00256         $status = $this->getConnection();
00257         if ( !$status->isOK() ) {
00258             throw new MWException( __METHOD__ . ': unexpected DB connection error' );
00259         }
00260         LBFactory::setInstance( new LBFactory_Single( array(
00261             'connection' => $status->value ) ) );
00262     }
00263 
00269     public function doUpgrade() {
00270         $this->setupSchemaVars();
00271         $this->enableLB();
00272 
00273         $ret = true;
00274         ob_start( array( $this, 'outputHandler' ) );
00275         $up = DatabaseUpdater::newForDB( $this->db );
00276         try {
00277             $up->doUpdates();
00278         } catch ( MWException $e ) {
00279             echo "\nAn error occurred:\n";
00280             echo $e->getText();
00281             $ret = false;
00282         }
00283         $up->purgeCache();
00284         ob_end_flush();
00285 
00286         return $ret;
00287     }
00288 
00294     public function preInstall() {
00295     }
00296 
00300     public function preUpgrade() {
00301     }
00302 
00307     public function getGlobalNames() {
00308         return $this->globalNames;
00309     }
00310 
00316     public function __construct( $parent ) {
00317         $this->parent = $parent;
00318     }
00319 
00327     protected static function checkExtension( $name ) {
00328         return extension_loaded( $name );
00329     }
00330 
00335     public function getReadableName() {
00336         // Messages: config-type-mysql, config-type-postgres, config-type-sqlite,
00337         // config-type-oracle
00338         return wfMessage( 'config-type-' . $this->getName() )->text();
00339     }
00340 
00346     public function getGlobalDefaults() {
00347         return array();
00348     }
00349 
00354     public function getInternalDefaults() {
00355         return $this->internalDefaults;
00356     }
00357 
00364     public function getVar( $var, $default = null ) {
00365         $defaults = $this->getGlobalDefaults();
00366         $internal = $this->getInternalDefaults();
00367         if ( isset( $defaults[$var] ) ) {
00368             $default = $defaults[$var];
00369         } elseif ( isset( $internal[$var] ) ) {
00370             $default = $internal[$var];
00371         }
00372 
00373         return $this->parent->getVar( $var, $default );
00374     }
00375 
00381     public function setVar( $name, $value ) {
00382         $this->parent->setVar( $name, $value );
00383     }
00384 
00394     public function getTextBox( $var, $label, $attribs = array(), $helpData = "" ) {
00395         $name = $this->getName() . '_' . $var;
00396         $value = $this->getVar( $var );
00397         if ( !isset( $attribs ) ) {
00398             $attribs = array();
00399         }
00400 
00401         return $this->parent->getTextBox( array(
00402             'var' => $var,
00403             'label' => $label,
00404             'attribs' => $attribs,
00405             'controlName' => $name,
00406             'value' => $value,
00407             'help' => $helpData
00408         ) );
00409     }
00410 
00421     public function getPasswordBox( $var, $label, $attribs = array(), $helpData = "" ) {
00422         $name = $this->getName() . '_' . $var;
00423         $value = $this->getVar( $var );
00424         if ( !isset( $attribs ) ) {
00425             $attribs = array();
00426         }
00427 
00428         return $this->parent->getPasswordBox( array(
00429             'var' => $var,
00430             'label' => $label,
00431             'attribs' => $attribs,
00432             'controlName' => $name,
00433             'value' => $value,
00434             'help' => $helpData
00435         ) );
00436     }
00437 
00443     public function getCheckBox( $var, $label, $attribs = array(), $helpData = "" ) {
00444         $name = $this->getName() . '_' . $var;
00445         $value = $this->getVar( $var );
00446 
00447         return $this->parent->getCheckBox( array(
00448             'var' => $var,
00449             'label' => $label,
00450             'attribs' => $attribs,
00451             'controlName' => $name,
00452             'value' => $value,
00453             'help' => $helpData
00454         ) );
00455     }
00456 
00470     public function getRadioSet( $params ) {
00471         $params['controlName'] = $this->getName() . '_' . $params['var'];
00472         $params['value'] = $this->getVar( $params['var'] );
00473 
00474         return $this->parent->getRadioSet( $params );
00475     }
00476 
00484     public function setVarsFromRequest( $varNames ) {
00485         return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' );
00486     }
00487 
00498     public function needsUpgrade() {
00499         $status = $this->getConnection();
00500         if ( !$status->isOK() ) {
00501             return false;
00502         }
00503 
00504         if ( !$this->db->selectDB( $this->getVar( 'wgDBname' ) ) ) {
00505             return false;
00506         }
00507 
00508         return $this->db->tableExists( 'cur', __METHOD__ ) ||
00509             $this->db->tableExists( 'revision', __METHOD__ );
00510     }
00511 
00517     public function getInstallUserBox() {
00518         return Html::openElement( 'fieldset' ) .
00519             Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) .
00520             $this->getTextBox(
00521                 '_InstallUser',
00522                 'config-db-username',
00523                 array( 'dir' => 'ltr' ),
00524                 $this->parent->getHelpBox( 'config-db-install-username' )
00525             ) .
00526             $this->getPasswordBox(
00527                 '_InstallPassword',
00528                 'config-db-password',
00529                 array( 'dir' => 'ltr' ),
00530                 $this->parent->getHelpBox( 'config-db-install-password' )
00531             ) .
00532             Html::closeElement( 'fieldset' );
00533     }
00534 
00539     public function submitInstallUserBox() {
00540         $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword' ) );
00541 
00542         return Status::newGood();
00543     }
00544 
00552     public function getWebUserBox( $noCreateMsg = false ) {
00553         $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
00554         $s = Html::openElement( 'fieldset' ) .
00555             Html::element( 'legend', array(), wfMessage( 'config-db-web-account' )->text() ) .
00556             $this->getCheckBox(
00557                 '_SameAccount', 'config-db-web-account-same',
00558                 array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
00559             ) .
00560             Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
00561             $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
00562             $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
00563             $this->parent->getHelpBox( 'config-db-web-help' );
00564         if ( $noCreateMsg ) {
00565             $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
00566         } else {
00567             $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
00568         }
00569         $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
00570 
00571         return $s;
00572     }
00573 
00579     public function submitWebUserBox() {
00580         $this->setVarsFromRequest(
00581             array( 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount' )
00582         );
00583 
00584         if ( $this->getVar( '_SameAccount' ) ) {
00585             $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
00586             $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
00587         }
00588 
00589         if ( $this->getVar( '_CreateDBAccount' ) && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
00590             return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
00591         }
00592 
00593         return Status::newGood();
00594     }
00595 
00601     public function populateInterwikiTable() {
00602         $status = $this->getConnection();
00603         if ( !$status->isOK() ) {
00604             return $status;
00605         }
00606         $this->db->selectDB( $this->getVar( 'wgDBname' ) );
00607 
00608         if ( $this->db->selectRow( 'interwiki', '*', array(), __METHOD__ ) ) {
00609             $status->warning( 'config-install-interwiki-exists' );
00610 
00611             return $status;
00612         }
00613         global $IP;
00614         wfSuppressWarnings();
00615         $rows = file( "$IP/maintenance/interwiki.list",
00616             FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
00617         wfRestoreWarnings();
00618         $interwikis = array();
00619         if ( !$rows ) {
00620             return Status::newFatal( 'config-install-interwiki-list' );
00621         }
00622         foreach ( $rows as $row ) {
00623             $row = preg_replace( '/^\s*([^#]*?)\s*(#.*)?$/', '\\1', $row ); // strip comments - whee
00624             if ( $row == "" ) {
00625                 continue;
00626             }
00627             $row .= "||";
00628             $interwikis[] = array_combine(
00629                 array( 'iw_prefix', 'iw_url', 'iw_local', 'iw_api', 'iw_wikiid' ),
00630                 explode( '|', $row )
00631             );
00632         }
00633         $this->db->insert( 'interwiki', $interwikis, __METHOD__ );
00634 
00635         return Status::newGood();
00636     }
00637 
00638     public function outputHandler( $string ) {
00639         return htmlspecialchars( $string );
00640     }
00641 }