MediaWiki  REL1_23
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             $msg = __METHOD__ . ': unexpected error while establishing'
00247                 . ' a database connection with message: '
00248                 . $status->getMessage()->plain();
00249             throw new MWException( $msg );
00250         }
00251     }
00252 
00258     public function enableLB() {
00259         $status = $this->getConnection();
00260         if ( !$status->isOK() ) {
00261             throw new MWException( __METHOD__ . ': unexpected DB connection error' );
00262         }
00263         LBFactory::setInstance( new LBFactorySingle( array(
00264             'connection' => $status->value ) ) );
00265     }
00266 
00272     public function doUpgrade() {
00273         $this->setupSchemaVars();
00274         $this->enableLB();
00275 
00276         $ret = true;
00277         ob_start( array( $this, 'outputHandler' ) );
00278         $up = DatabaseUpdater::newForDB( $this->db );
00279         try {
00280             $up->doUpdates();
00281         } catch ( MWException $e ) {
00282             echo "\nAn error occurred:\n";
00283             echo $e->getText();
00284             $ret = false;
00285         }
00286         $up->purgeCache();
00287         ob_end_flush();
00288 
00289         return $ret;
00290     }
00291 
00297     public function preInstall() {
00298     }
00299 
00303     public function preUpgrade() {
00304     }
00305 
00310     public function getGlobalNames() {
00311         return $this->globalNames;
00312     }
00313 
00319     public function __construct( $parent ) {
00320         $this->parent = $parent;
00321     }
00322 
00330     protected static function checkExtension( $name ) {
00331         return extension_loaded( $name );
00332     }
00333 
00338     public function getReadableName() {
00339         // Messages: config-type-mysql, config-type-postgres, config-type-sqlite,
00340         // config-type-oracle
00341         return wfMessage( 'config-type-' . $this->getName() )->text();
00342     }
00343 
00349     public function getGlobalDefaults() {
00350         return array();
00351     }
00352 
00357     public function getInternalDefaults() {
00358         return $this->internalDefaults;
00359     }
00360 
00367     public function getVar( $var, $default = null ) {
00368         $defaults = $this->getGlobalDefaults();
00369         $internal = $this->getInternalDefaults();
00370         if ( isset( $defaults[$var] ) ) {
00371             $default = $defaults[$var];
00372         } elseif ( isset( $internal[$var] ) ) {
00373             $default = $internal[$var];
00374         }
00375 
00376         return $this->parent->getVar( $var, $default );
00377     }
00378 
00384     public function setVar( $name, $value ) {
00385         $this->parent->setVar( $name, $value );
00386     }
00387 
00397     public function getTextBox( $var, $label, $attribs = array(), $helpData = "" ) {
00398         $name = $this->getName() . '_' . $var;
00399         $value = $this->getVar( $var );
00400         if ( !isset( $attribs ) ) {
00401             $attribs = array();
00402         }
00403 
00404         return $this->parent->getTextBox( array(
00405             'var' => $var,
00406             'label' => $label,
00407             'attribs' => $attribs,
00408             'controlName' => $name,
00409             'value' => $value,
00410             'help' => $helpData
00411         ) );
00412     }
00413 
00424     public function getPasswordBox( $var, $label, $attribs = array(), $helpData = "" ) {
00425         $name = $this->getName() . '_' . $var;
00426         $value = $this->getVar( $var );
00427         if ( !isset( $attribs ) ) {
00428             $attribs = array();
00429         }
00430 
00431         return $this->parent->getPasswordBox( array(
00432             'var' => $var,
00433             'label' => $label,
00434             'attribs' => $attribs,
00435             'controlName' => $name,
00436             'value' => $value,
00437             'help' => $helpData
00438         ) );
00439     }
00440 
00450     public function getCheckBox( $var, $label, $attribs = array(), $helpData = "" ) {
00451         $name = $this->getName() . '_' . $var;
00452         $value = $this->getVar( $var );
00453 
00454         return $this->parent->getCheckBox( array(
00455             'var' => $var,
00456             'label' => $label,
00457             'attribs' => $attribs,
00458             'controlName' => $name,
00459             'value' => $value,
00460             'help' => $helpData
00461         ) );
00462     }
00463 
00477     public function getRadioSet( $params ) {
00478         $params['controlName'] = $this->getName() . '_' . $params['var'];
00479         $params['value'] = $this->getVar( $params['var'] );
00480 
00481         return $this->parent->getRadioSet( $params );
00482     }
00483 
00491     public function setVarsFromRequest( $varNames ) {
00492         return $this->parent->setVarsFromRequest( $varNames, $this->getName() . '_' );
00493     }
00494 
00505     public function needsUpgrade() {
00506         $status = $this->getConnection();
00507         if ( !$status->isOK() ) {
00508             return false;
00509         }
00510 
00511         if ( !$this->db->selectDB( $this->getVar( 'wgDBname' ) ) ) {
00512             return false;
00513         }
00514 
00515         return $this->db->tableExists( 'cur', __METHOD__ ) ||
00516             $this->db->tableExists( 'revision', __METHOD__ );
00517     }
00518 
00524     public function getInstallUserBox() {
00525         return Html::openElement( 'fieldset' ) .
00526             Html::element( 'legend', array(), wfMessage( 'config-db-install-account' )->text() ) .
00527             $this->getTextBox(
00528                 '_InstallUser',
00529                 'config-db-username',
00530                 array( 'dir' => 'ltr' ),
00531                 $this->parent->getHelpBox( 'config-db-install-username' )
00532             ) .
00533             $this->getPasswordBox(
00534                 '_InstallPassword',
00535                 'config-db-password',
00536                 array( 'dir' => 'ltr' ),
00537                 $this->parent->getHelpBox( 'config-db-install-password' )
00538             ) .
00539             Html::closeElement( 'fieldset' );
00540     }
00541 
00546     public function submitInstallUserBox() {
00547         $this->setVarsFromRequest( array( '_InstallUser', '_InstallPassword' ) );
00548 
00549         return Status::newGood();
00550     }
00551 
00559     public function getWebUserBox( $noCreateMsg = false ) {
00560         $wrapperStyle = $this->getVar( '_SameAccount' ) ? 'display: none' : '';
00561         $s = Html::openElement( 'fieldset' ) .
00562             Html::element( 'legend', array(), wfMessage( 'config-db-web-account' )->text() ) .
00563             $this->getCheckBox(
00564                 '_SameAccount', 'config-db-web-account-same',
00565                 array( 'class' => 'hideShowRadio', 'rel' => 'dbOtherAccount' )
00566             ) .
00567             Html::openElement( 'div', array( 'id' => 'dbOtherAccount', 'style' => $wrapperStyle ) ) .
00568             $this->getTextBox( 'wgDBuser', 'config-db-username' ) .
00569             $this->getPasswordBox( 'wgDBpassword', 'config-db-password' ) .
00570             $this->parent->getHelpBox( 'config-db-web-help' );
00571         if ( $noCreateMsg ) {
00572             $s .= $this->parent->getWarningBox( wfMessage( $noCreateMsg )->plain() );
00573         } else {
00574             $s .= $this->getCheckBox( '_CreateDBAccount', 'config-db-web-create' );
00575         }
00576         $s .= Html::closeElement( 'div' ) . Html::closeElement( 'fieldset' );
00577 
00578         return $s;
00579     }
00580 
00586     public function submitWebUserBox() {
00587         $this->setVarsFromRequest(
00588             array( 'wgDBuser', 'wgDBpassword', '_SameAccount', '_CreateDBAccount' )
00589         );
00590 
00591         if ( $this->getVar( '_SameAccount' ) ) {
00592             $this->setVar( 'wgDBuser', $this->getVar( '_InstallUser' ) );
00593             $this->setVar( 'wgDBpassword', $this->getVar( '_InstallPassword' ) );
00594         }
00595 
00596         if ( $this->getVar( '_CreateDBAccount' ) && strval( $this->getVar( 'wgDBpassword' ) ) == '' ) {
00597             return Status::newFatal( 'config-db-password-empty', $this->getVar( 'wgDBuser' ) );
00598         }
00599 
00600         return Status::newGood();
00601     }
00602 
00608     public function populateInterwikiTable() {
00609         $status = $this->getConnection();
00610         if ( !$status->isOK() ) {
00611             return $status;
00612         }
00613         $this->db->selectDB( $this->getVar( 'wgDBname' ) );
00614 
00615         if ( $this->db->selectRow( 'interwiki', '*', array(), __METHOD__ ) ) {
00616             $status->warning( 'config-install-interwiki-exists' );
00617 
00618             return $status;
00619         }
00620         global $IP;
00621         wfSuppressWarnings();
00622         $rows = file( "$IP/maintenance/interwiki.list",
00623             FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES );
00624         wfRestoreWarnings();
00625         $interwikis = array();
00626         if ( !$rows ) {
00627             return Status::newFatal( 'config-install-interwiki-list' );
00628         }
00629         foreach ( $rows as $row ) {
00630             $row = preg_replace( '/^\s*([^#]*?)\s*(#.*)?$/', '\\1', $row ); // strip comments - whee
00631             if ( $row == "" ) {
00632                 continue;
00633             }
00634             $row .= "||";
00635             $interwikis[] = array_combine(
00636                 array( 'iw_prefix', 'iw_url', 'iw_local', 'iw_api', 'iw_wikiid' ),
00637                 explode( '|', $row )
00638             );
00639         }
00640         $this->db->insert( 'interwiki', $interwikis, __METHOD__ );
00641 
00642         return Status::newGood();
00643     }
00644 
00645     public function outputHandler( $string ) {
00646         return htmlspecialchars( $string );
00647     }
00648 }